【问题标题】:Extending vector iterator to fill my needs扩展向量迭代器以满足我的需求
【发布时间】:2010-09-28 16:04:23
【问题描述】:

我的一个项目中有以下设计:

template<typename C> class B {
    int numValue;
    C inner;
}

template<typename C> class A {
    vector<B<C>> container;
    ...
    Iterator InsertItem(C item) {...}
}

我想要的是一种修改现有向量迭代器以返回迭代器的方法,该迭代器将在解除引用时返回 &inner 而不是返回对 B 对象的引用。 希望它不需要完整的迭代器类实现。

【问题讨论】:

  • 为什么不直接做iter-&gt;inner?

标签: c++ templates iterator


【解决方案1】:

这样的迭代器是Boost.TransformIterator

示例(填写你的代码,并不是说它是特别好的设计)。

#include <vector>
#include <iostream>
#include <functional>
#include <boost/iterator/transform_iterator.hpp>
using namespace std;

template<typename C> struct B {
    int numValue;
    C inner;
};

template <class T>
struct get_inner: std::unary_function<B<T>&, T&>
{
    T& operator()(B<T>& value) const { return value.inner; }
};

template<typename C> struct A {
    vector<B<C> > container;
    typedef boost::transform_iterator<get_inner<C>, typename vector<B<C> >::iterator> Iterator;
    Iterator InsertItem(C item) {
        B<C> b = {0, item};
        container.push_back(b);
        return Iterator(--container.end());
    }
};

int main()
{
    A<double> a;
    A<double>::Iterator it = a.InsertItem(3.14);
    std::cout << *it << '\n';
}

【讨论】:

  • 确实,这似乎是一个不那么痛苦的解决方案,但我不喜欢在我的项目中引入一些提升依赖的想法。
【解决方案2】:

我根本看不出您需要在哪里修改迭代器。相反,您只需要向 B 添加一些成员函数,它们将适当的迭代器返回到内部:

template <class C>
class B { 
    C inner;
public:

    typedef typename C::iterator iterator;
    typedef typename C::const_iterator const_iterator;
    // etc.

    iterator begin() { return inner.begin(); }
    iterator end()   { return inner.end(); }

    // and so on for rbegin, rend, cbegin, cend, ...
};

编辑:我应该补充一点,如果你想支持(例如)back_insert_iterator,你还需要在 B 中添加一个push_back,你也(可能)通过转发来实现它到C::push_back。

【讨论】:

  • 问题在哪里说或暗示C 是一个容器类?
  • @Mark:迭代器意味着迭代。由于 B 不是容器类,因此为了使迭代更有意义,C 几乎需要。如果 C 至少不是模糊地类似于容器,那么迭代器将迭代什么?当然,C 可以是一个数组(例如),在这种情况下,您需要自己做更多的工作,但没有相反的具体陈述,我认为他足够明智,可以避免使用原始数组。
  • A 包含一个向量,我认为这是需要迭代的。
  • 如果这就是他所追求的,他基本上已经“从里到外”了——他所需要的与迭代器根本没有关系,而是一种使 B 充当 C 代理的方法(相当简单,但完全不同)。
【解决方案3】:

如果您的迭代器返回&amp;inner,您将如何访问numValue?

如果您创建自己的 A::iterator,它应该很容易包含 vector&lt;B&lt;C&gt;&gt;::iterator 并通过它转发大多数操作。是的,您需要一个完整的迭代器类实现,但这一点也不难。

【讨论】:

  • 我想我会按照你的建议用嵌入式向量编写自己的迭代器类型>::iterator,但我找不到关于编写自定义迭代器的好教程;我应该让它继承自 std::iterator 吗?
  • @user456668:是的,您应该从std::iterator 继承,尽管这只是提供了一些类型定义并使iterator_traits 可用于该类型。否则,您只需要重载 vector::iterator 所做的所有运算符(转发到底层迭代器)并在运算符 *、-&gt; 和 [] 中执行特殊操作。
【解决方案4】:

使用boost::transform_iterator 创建一个新的迭代器来包装您的向量迭代器,但生成inner 值:

template<typename C>
C& getInner(B<C>& b)
{
    return b.inner;
}    

vector<B<C>> container;
typedef boost::transform_iterator<C&(*)(B<C>&), vector<B<C> >::iterator> inner_iterator;
inner_iterator it=boost::make_transform_iterator(container.begin(), getInner<C>)

【讨论】:

    猜你喜欢
    • 2016-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-08
    • 1970-01-01
    • 2021-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多