I came up with this solution. Not very "sexy", but it should work:
#include <type_traits>
#include <iterator>
#include <utility>
#include <boost/optional.hpp>
namespace pair_iterator {
template <class A, class B, class Pair>
class PairIterator {
public:
    using iterator_category = std::random_access_iterator_tag;
    using value_type = std::common_type_t<A, B>;
    using difference_type = std::ptrdiff_t;
    using pointer = std::add_pointer_t<value_type>;
    using reference = std::add_lvalue_reference_t<value_type>;
    using const_reference = std::add_lvalue_reference_t<const value_type>;
private:
    boost::optional<Pair &> pair = {};
    difference_type index = 2;
public:
    PairIterator(
        const boost::optional<Pair &> &pair = {},
        difference_type index = 2
    ) : pair(pair), index(index) {}
    // Iterator
    PairIterator(PairIterator&&) = default;
    PairIterator(const PairIterator&) = default;
    PairIterator &operator =(PairIterator&&) = default;
    PairIterator &operator =(const PairIterator&) = default;
    ~PairIterator() = default;
    void swap(PairIterator &other) {
        std::swap(pair, other.pair);
        std::swap(index, other.index);
    }
    reference operator *() {
        return index == 0 ? pair->first : pair->second;
    }
    const_reference operator *() const {
        return index == 0 ? pair->first : pair->second;
    }
    PairIterator &operator ++() {
        ++index;
        return *this;
    }
    // InputIterator
    bool operator ==(const PairIterator &other) const {
        return index == other.index;
    }
    bool operator !=(const PairIterator &other) const {
        return index != other.index;
    }
    PairIterator operator ++(int) const {
        return { pair, index+1 };
    }
    // ForwardIterator
    // BidirectionalIterator
    PairIterator &operator --() {
        --index;
        return *this;
    }
    PairIterator operator --(int) const {
        return { pair, index-1 };
    }
    // RandomAccessIterator
    PairIterator &operator +=(difference_type n) {
        index += n;
        return *this;
    }
    PairIterator operator +(difference_type n) const {
        return { pair, index+n };
    }
    PairIterator &operator -=(difference_type n) {
        index -= n;
        return *this;
    }
    PairIterator operator -(difference_type n) const {
        return { pair, index-n };
    }
    difference_type operator -(const PairIterator &other) const {
        return index - other.index;
    }
    reference operator [](difference_type n) {
        return (index+n) == 0 ? pair->first : pair->second;
    }
    const_reference operator [](difference_type n) const {
        return (index+n) == 0 ? pair->first : pair->second;
    }
    bool operator <(const PairIterator &other) const {
        return index < other.index;
    }
    bool operator >(const PairIterator &other) const {
        return index > other.index;
    }
    bool operator <=(const PairIterator &other) const {
        return index <= other.index;
    }
    bool operator >=(const PairIterator &other) const {
        return index >= other.index;
    }
};
template <class A, class B>
auto begin(std::pair<A, B> &pair) ->
PairIterator<A, B, std::pair<A, B>> {
    return { pair, 0 };
}
template <class A, class B>
auto end(std::pair<A, B> &pair) ->
PairIterator<A, B, std::pair<A, B>> {
    return { pair, 2 };
}
template <class A, class B>
auto begin(const std::pair<A, B> &pair) ->
PairIterator<const A, const B, const std::pair<A, B>> {
    return { pair, 0 };
}
template <class A, class B>
auto end(const std::pair<A, B> &pair) ->
PairIterator<const A, const B, const std::pair<A, B>> {
    return { pair, 2 };
}
} // namespace pair_iterator
namespace std {
using pair_iterator::begin;
using pair_iterator::end;
} // namespace std