c – 具有复杂值类型的迭代器:与value_type和引用混淆
我想创建一个自定义迭代器包装器,例如,枚举:给定一对类型为T的迭代器,它将返回一个可迭代的类型std :: pair< const int,T&>,其中该对的第一个元素将取值0,1,2,依此类推.
我有一个问题,弄清楚什么应该是value_type和我的迭代器的引用.我想支持两种行为: 首先,引用基础序列的值: for (auto& kv: enumerate(my_vec)) { kv.second = kv.first; } (有点std :: iota); 第二,制作价值的副本: std::vector<int> a{10,20,30}; auto copy = *enumerate(a).begin(); a[0] = 15; std::cout << copy.first << " " << copy.second; // 0 10 我很困惑应该是Iterator :: operator *()的返回类型.如果它是std :: pair< const int,T&>然后在第二个示例中,不会复制值.如果它是std :: pair< const int,则T>那么在第一个例子中,不可能引用基础值.我该怎么做以及这个迭代器的value_type,reference和pointer typedef应该是什么? 这是我尝试实现它.它支持获取引用但不支持复制. template<typename T> struct Iterator { using TT = typename std::iterator_traits<T>::value_type; using value_type = std::pair<const int,TT>; using reference = std::pair<const int&,typename std::iterator_traits<T>::reference>; using pointer = value_type*; using iterator_category = std::forward_iterator_tag; using difference_type = std::ptrdiff_t; std::pair<int,T> it; Iterator(T iterator) : it(0,iterator) {} bool operator==(const Iterator& other) const { return it.second == other.it.second; } bool operator!=(const Iterator& other) const { return it.second != other.it.second; } reference operator*() { return { it.first,*it.second }; } Iterator& operator++() { ++it.first; ++it.second; return *this; } }; 附:我刚刚检查过,boost :: adapters :: index遇到了同样的问题并且没有复制该值. 解决方法
这个问题类似于std :: vector< bool>,你想提供一个代理,它就像一个引用,但也支持值语义.
然而,有所不同的是,涉及的类型不受限制,涉及两个参考,并且弹出各种毛羽.以下是部分实现,它说明了您遇到的一些问题 #include<iterator> #include<functional> template<typename F,typename S,bool defined = true> struct sfinae_difference_type {}; template<typename F,typename S> struct sfinae_difference_type<F,S,std::is_same_v<typename std::iterator_traits<F>::difference_type,typename std::iterator_traits<S>::difference_type>> { using difference_type = typename std::iterator_traits<F>::difference_type; }; template<typename F,typename S> class pair_iterator : sfinae_difference_type<F,S> { using Fvalue_type = typename std::iterator_traits<F>::value_type; using Svalue_type = typename std::iterator_traits<S>::value_type; using Freference = typename std::iterator_traits<F>::reference; using Sreference = typename std::iterator_traits<S>::reference; F f; S s; public: using value_type = std::pair<Fvalue_type,Svalue_type>; struct reference { Freference first; Sreference second; reference() = delete; reference(const reference& other) : first{other.first},second{other.second} {} reference& operator=(const reference& rhs) { first = rhs.first; second = rhs.second; return *this; } operator value_type() { return {f,s}; } private: reference(Freference f,Sreference s) : first{f},second{s} {} friend pair_iterator; }; struct pointer { // similar to reference }; pair_iterator() = default; pair_iterator(const pair_iterator&) = default; pair_iterator(F f,S s) : f{f},s{s} {} pair_iterator& operator++() { ++f; ++s; return *this; } reference operator*() { return {*f,*s}; } pointer operator->() { return {f.operator->(),s.operator->()}; } bool operator==(const pair_iterator& other) { return f == other.f && s == other.s; } }; 然后你用它作为 #include<vector> #include<list> #include<iostream> int main() { std::vector v{1,3,4,5}; std::list l{6,7,8,9,10}; pair_iterator begin{v.begin(),l.begin()},end{v.end(),l.end()}; for(; begin != end; ++begin) std::cout << begin->first << ' ' << begin->second << 'n'; } Live 一些直接明显的问题: >实施繁琐.有sfinae友好型别名和适当的代理需要丰富的样板. 所有这些必须被敲定以使其工作,并没有一个简单的答案. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |