11

我写了一个稀疏向量类(见#1#2。)

我想提供两种迭代器:

第一个集合,常规迭代器,可以指向任何元素,无论是设置的还是未设置的。如果它们被读取,它们返回设置值,或者value_type(),如果它们被写入,它们创建元素并返回左值引用。因此,它们是:

随机访问遍历迭代器可读迭代器

第二个集合,稀疏迭代器,仅迭代集合元素。由于它们不需要懒惰地创建写入的元素,因此它们是:

随机访问遍历迭代器可读左值迭代器

我还需要两者的 const 版本,它们是不可写的。

我可以填空,但不确定如何使用 boost::iterator_adaptor 开始。

这是我到目前为止所拥有的:

template<typename T>
class sparse_vector {
public:
    typedef size_t size_type;
    typedef T value_type;

private:
    typedef T& true_reference;
    typedef const T* const_pointer;
    typedef sparse_vector<T> self_type;
    struct ElementType {
        ElementType(size_type i, T const& t): index(i), value(t) {}
        ElementType(size_type i, T&& t): index(i), value(t) {}
        ElementType(size_type i): index(i) {}
        ElementType(ElementType const&) = default;
        size_type index;
        value_type value;
    };
    typedef vector<ElementType> array_type;

public:
    typedef T* pointer;
    typedef T& reference;
    typedef const T& const_reference;

private:
    size_type                                   size_;
    mutable typename array_type::size_type      sorted_filled_; 
    mutable array_type                          data_;

// lots of code for various algorithms...

public:    
    class sparse_iterator
        : public boost::iterator_adaptor<
          sparse_iterator                   // Derived
          , typename array_type::iterator            // Base (the internal array)
          , value_type              // Value
          , boost::random_access_traversal_tag    // CategoryOrTraversal
          > {...}

    class iterator_proxy {
          ???
    };

    class iterator
        : public boost::iterator_facade<
          iterator                          // Derived
          , ?????                           // Base
          , ?????              // Value
          , boost::??????    // CategoryOrTraversal
          > {
    };
};

还有,这是违法的吗?

typedef boost::reverse_iterator<sparse_iterator> reverse_sparse_iterator;
4

1 回答 1

19

我不确定你真的想iterator_adaptor在你的情况下使用 - 你可能想iterator_facade改用。

更彻底的解释:iterator_adaptors当你有一个现有的迭代器(比如说std::list<int>::iterator)并且想要为你的迭代器重用它的行为时使用,例如。您的迭代器将返回列表中值的两倍,但会重用原始迭代器中的遍历代码。或者反过来:你可能想要一个迭代器,它会跳过原始列表中的一些元素,但返回值不变。我不确定你是否想将你的迭代器(如重用代码)基于你的底层结构的迭代器,但对我来说,我不会特别是在非稀疏迭代器的情况下,因为你可能想要创建一些引用的代理,这意味着您不能使用任何底层迭代器dereference()代码,并且遍历可能很容易。但是,您可以根据您的sparse_iterator如果需要,可以在某个迭代器上迭代数组中实际存在的元素。

代理方法存在一些问题,所以不要指望它可以完美地工作而无需经历很多麻烦。一方面,非稀疏迭代器的 const 版本仍然应该 return ,这意味着如果相应的条目不存在value_type(),则表达式iter->foo()应该转换为。value_type().foo()但这带来了一个困难,它pointer_proxy::operator->()应该返回一些带有的东西operator->,最好是一个指针(绝对不是value_type())。这就引出了一个关键问题:指向什么的指针?有可能解决这个问题(例如,如果您的对象由 管理boost::shared_pointer,您可以将 a 返回shared_pointer到一个new'd 实例)。

对于非稀疏迭代器,您需要实现:

  • class reference_proxy
  • reference_proxy::operator&(这可能会返回一个指针代理)
  • reference_proxy::operator value_type&()用于 const 用途
  • reference_proxy::operator const value_type&()用于非常量用途
  • reference_proxy::foo()对于 value_type 的任何foo()成员函数(否则像(*it).foo()AFAIK 这样的表达式将不起作用)

  • class pointer_proxy

  • pointer_proxy::operator*(返回一个reference_proxy)
  • pointer_proxy::operator->(做一些明智的事情,见上文)

迭代器外观模板的参数应该是:

  • Reference: 这reference_proxy
  • Pointer: 这pointer_proxy

稀疏版本更简单:如果底层迭代器是明智的(即匹配您想要的行为)并且正确实现,您可以省略参数iterator_adaptor(除了前两个),并获取所有实现。

“不编译”问题: insert typename

于 2010-05-12T21:56:57.580 回答