왜 std::pair
에는 반복자가 있습니까? 왜 std :: pair에는 반복자가 없습니까?
std::pair
iterator
및
const_iterator
뿐만 아니라
begin()
및
end()
을 제공해야한다 - 단지 자신의 두 멤버.
vector
또는 set
과 같이 iterables를 예상하는 템플릿 기능에 전달할 수 있기 때문에 유용하다고 생각합니다.
여기에 단점이 있습니까?
왜 std::pair
에는 반복자가 있습니까? 왜 std :: pair에는 반복자가 없습니까?
std::pair
iterator
및
const_iterator
뿐만 아니라
begin()
및
end()
을 제공해야한다 - 단지 자신의 두 멤버.
vector
또는 set
과 같이 iterables를 예상하는 템플릿 기능에 전달할 수 있기 때문에 유용하다고 생각합니다.
여기에 단점이 있습니까?
한 가지 이유는 한 쌍의 두 요소가 다른 유형이 될 수 있기 때문입니다. 이것은 반복자 모델에 맞지 않습니다.
반복자를 사용하는 튜플이 더 매력적일 수 있습니다.
고정 길이의 균질 한 컨테이너가 필요하면 std::array<T, n>
을 사용할 수 있습니다.
std::pair
의 목적은 전통적인 컨테이너가 아니라 두 개의 잠재적으로 이기종 객체를 단일 컨테이너로 처리 할 수있는 튜플 역할을하는 것입니다.
또한 쌍의 두 부분에 모두 직접 액세스 할 수 있고 쌍을 이루는 형식이 동일하지 않을 수 있으므로 반복기는 적합하지 않습니다.
pair<T,T>
에만 적용되는 것 외에 다른 특정 단점이 있다고 생각하지 않습니다. pair<T,U>
이 아닙니다. 물론
#include <utility>
#include <iterator>
#include <vector>
#include <iostream>
namespace itpair {
template <typename T>
struct pair_iterator : std::iterator<std::forward_iterator_tag, T> {
std::pair<T,T> *container;
int idx;
pair_iterator(std::pair<T,T> *container, int idx) : container(container), idx(idx) {}
T &operator*() const {
return idx ? container->second : container->first;
}
T *operator->() const {
return &*this;
}
friend pair_iterator &operator++(pair_iterator &self) {
self.idx += 1;
return self;
}
friend pair_iterator operator++(pair_iterator &self, int) {
pair_iterator result = self;
++self;
return result;
}
friend bool operator==(const pair_iterator &self, const pair_iterator &other) {
return self.container == other.container && self.idx == other.idx;
}
friend bool operator!=(const pair_iterator &self, const pair_iterator &other) {
return !(self == other);
}
};
template <typename T>
pair_iterator<T> begin(std::pair<T,T> &p) {
return pair_iterator<T>(&p, 0);
}
template <typename T>
pair_iterator<T> end(std::pair<T,T> &p) {
return pair_iterator<T>(&p, 2);
}
}
int main() {
std::pair<int,int> p = std::make_pair(1, 2);
using namespace itpair;
std::vector<int> v(begin(p), end(p));
std::cout << v[0] << " " << v[1] << "\n";
}
당신은 너무 const_iterator
을 원하고, 다음 당신은 (더 연산자를 의미) 랜덤 액세스되고 싶었다됩니다.
모든 사람들이 말하듯이, 그건 실제로는 pair
이 아닙니다. 그것은 단지 컨테이너가 아닙니다.
이 솔루션을 생각해 냈습니다. 별로 섹시하지는 않지만 작동해야합니다 :
#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
'std :: pair'. 반복자는 동종 컨테이너에서만 작동합니다. –
'std :: pair '가 때로는 범위로 사용되지만, 그것에 관해서는 아무것도 사용하거나 권장하지 않습니다. 그래서 그렇게 전문적이지는 않을 것입니다. C++ 11의 초기 초안에는 실제로이 부분이있었습니다. http://stackoverflow.com/questions/6167598/why-was-pair-range-access-removed-from-c11 –
당신이 자신의 객체를 그러한 템플릿 기능에 전달하고자한다면'std : : 배열'std :: pair '보다는 오히려. –
leftaroundabout