【发布时间】:2014-12-11 19:59:50
【问题描述】:
在定义我的自定义容器时,只需添加 size() 和 [] 就可以更简单且非常通用(对我而言)使它们可迭代。也就是说,具有以下成员方法:
unsigned int size() const { . . . }
T & operator[] (unsigned int pos) { . . . }
为了从 STL 算法中受益,我提供了一个适配器 从具有上述方法的 any 容器类到对 STL 函数有效的迭代器。 有了它,我可以轻松写出类似的东西
MyContainer<int, 5> mc;
IteratorFromContainer<MyContainer<int,5>, int> iter (&mc);
int i=1; for (auto & e : iter) { e = i++; }
for (auto e=iter.begin(); e!=iter.end(); ++e) { cout << (*e) << endl; }
int sum = std::accumulate(iter.begin(), iter.end(), 0);
int prod = std::accumulate(iter.begin(), iter.end(), 1, [](int a, int b) {return a*b;});
令人惊讶的是(对我来说)我的适配器(模板)类(上面的示例代码)同样有效 具有以下任何一项(1、2 或 3):
template<typename Container, typename T>
// 1.
class IteratorFromContainer : public std::iterator<input_iterator_tag, T> {
// 2.
class IteratorFromContainer : public std::iterator<output_iterator_tag, T> {
// 3.
class IteratorFromContainer {
为什么?适配器不应该从std::iterator always 派生吗?
我应该使用什么样的迭代器(什么_tag),考虑到迭代器是基于随机访问(size()和[])并且具有输出和输入能力:RandomAccess, ContinguousIterator?
谢谢
【问题讨论】:
-
请注意,在您的示例中,
IteratorFromContainer似乎根本没有尝试成为迭代器。它是一个适配器类,本身是可迭代的。iter.begin()的类型应该是一个迭代器。什么类型的迭代器取决于该类型的接口,但我推测它很容易使其随机访问,这将使用std::random_access_iterator_tag。 -
另外,如果你很狡猾,你不需要别人把
T传给IteratorFromContainer,你可以从decltype(mc[0])推导出来。 -
IteratorFromContainer需要实现给定迭代器标签对应的功能(如std::output_iterator_tag)。iterator基类只提供一些类型定义。如果它没有,当使用它的代码没有使用它承诺但没有的功能时,迭代器可能仍然工作。 C++17 中的概念可能会让编译器在这种情况下产生错误。 -
@cibercitizen1:这……很奇怪,我建议不要这样做。最好有一个除了创建迭代器之外什么都不做的给定线适配器类。