【发布时间】:2015-02-19 09:08:37
【问题描述】:
我有一个类似于容器的 C++ 类:它有 size() 和 operator[] 成员函数。存储在容器“中”的值是 std::tuple 对象。然而,容器实际上并没有将元组保存在内存中。相反,它根据以不同形式存储的基础数据按需构建它们。
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 是一个迭代器实例),据我所知,operator->函数需要返回一个指针。
当然,我不能返回指向按需构建的临时元组的指针。想到的一种可能性是将元组实例作为成员变量放入迭代器中,并使用它来存储迭代器当前定位的任何值的副本:
class Iterator {
private:
MyContainer *container;
std::size_t current_index;
// Copy of (*container)[current_index]
std::tuple<int, int, int> current_value;
// ...
};
但是,更新存储的值将需要迭代器检查其当前索引是否小于容器的大小,以便结束后迭代器不会通过访问底层数组的末尾而导致未定义的行为.这会增加(少量)运行时开销——当然,这不足以使解决方案不切实际,但感觉有点不雅。迭代器实际上不需要存储任何东西,只需要一个指向它正在迭代的容器的指针和其中的当前位置。
对于按需构造其值的迭代器类型,是否有一种干净、完善的方法来支持 operator->?其他开发人员会如何做这种事情?
(请注意,我根本需要支持operator-> — 我主要是实现迭代器以便可以使用 C++11 遍历容器“@987654323 @" 循环,而std::tuple 没有任何成员通常希望通过-> 访问。但我仍然想正确地建模迭代器概念;否则感觉就像我在偷工减料。还是我不应该打扰?)
【问题讨论】:
-
operator->不必返回指针。它只需要返回可以应用*的东西。 -
嗯,所以我可以返回一个“假指针”,它包含一个值并在“取消引用”时返回该值?我不确定这是否比将值存储在迭代器本身中更尴尬。 :-) 但至少(使用内联)运行时开销为零。
-
无论如何,要建模
ForwardIterator,您必须满足以下要求:“如果 a 和 b 都是可解引用的,那么 a == b 当且仅当 *a 和 *b 绑定到同一个对象。”这通常意味着返回代理或包含值的迭代器只能是 InputIterators -
@KerrekSB,看起来返回值实际上必须支持
->,而不是*。具有自己的operator->(返回真实指针)的伪指针类可以工作,但在伪指针中仅实现operator*()是行不通的。 -
[over.ref]/1: "如果
T::operator->()存在且运算符为被重载解析机制(13.3)选为最佳匹配函数。”
标签: c++ c++11 iterator operator-overloading