std::tuple<int,int,int> MyContainer::operator[](std::size_t n) const { // Example: draw corresponding elements from parallel arrays return { underlying_data_a[n],underlying_data_b[n],underlying_data_c[n] }; }
因此,operator []的返回类型是临时对象,而不是引用. (这意味着它不是左值,因此容器是只读的;没关系.)
现在我正在编写一个迭代器类,可用于遍历此容器中的元组.我想建模RandomAccessIterator,这取决于InputIterator,但是InputIterator需要支持表达式i-> m(其中i是迭代器实例),据我所知,运算符 – >函数需要返回一个指针.
当然,我无法返回指向按需构建的临时元组的指针.想到的一种可能性是将一个元组实例作为成员变量放入迭代器中,并使用它来存储迭代器当前所处的任何值的副本:
class Iterator { private: MyContainer *container; std::size_t current_index; // Copy of (*container)[current_index] std::tuple<int,int> current_value; // ... };
但是,更新存储的值将需要迭代器检查其当前索引是否小于容器的大小,以便过去的迭代器不会通过访问基础数组的末尾来导致未定义的行为.这增加了(少量)运行时开销 – 当然不足以使解决方案变得不切实际,但感觉有点不雅.迭代器不应该真正存储任何东西,除了指向它正在迭代的容器的指针以及它内部的当前位置.
是否有一种干净,完善的方式来支持操作符>对于按需构造其值的迭代器类型?其他开发人员将如何做这类事情?
(注意,我根本不需要支持operator-> – 我实现迭代器主要是为了能够使用C 11“range for”循环遍历容器,并且std :: tuple没有无论如何,通常会想要访问的任何成员 – >但是我仍然想要正确地模拟迭代器概念;否则我感觉就像是在偷工减料.或者我应该不打扰?)
解决方法
template<class T> struct pseudo_ptr { T t; T operator*()&&{return t;} T* operator->(){ return &t; } };
然后
struct bar { int x,y; }; struct bar_iterator:std::iterator< blah,blah >{ // ... pseudo_ptr<bar> operator->() const { return {**this}; } // ... };
这取决于如何 – >作品.
指针ptr的ptr-> b是简单的(* ptr).b.
否则,它被定义为(ptr.operator->()) – > b.如果operator->这将递归地评估.不返回指针.
pseudo_ptr< T>上面给你一个T副本的包装.
但请注意,终身扩展并不真正起作用.结果很脆弱.