【问题标题】:Custom class iterator following a list of integer indices?遵循整数索引列表的自定义类迭代器?
【发布时间】:2019-04-03 00:23:02
【问题描述】:

我有一个模板类 myClass,它拥有一个 std::vector 的实例,并且我重载了 [] 运算符以将成员向量上的索引 std::vector<int> 作为参数并返回一个辅助班级mySubset

template <typename _type> 
class myClass {
    // ...
    std::vector<_type> data;
    // ...
    class mySubset {
        myClass<_type>* mc; 
        const std::vector<int>::iterator &idx; 
    public:
        //constructor
        mySubset(myClass<_type> * _m, const std::vector<int>& _idx);
        // input operator overloads (for data and range input)
        template <typename _input_type> mySubset& operator=(const std::vector<_input_type>& _vals);
        mySubset& operator=(const mySubset& _sbst);
    };

public:

    myClass();
    ~myClass(); 
    // ...
    //acess operator
    mySubset operator[](const std::vector<int>& _idx) { return mySubset(_idx); };
    // ...
    //iterator
    typename std::vector<_type>::iterator begin() {return data.begin();};
    typename std::vector<_type>::iterator end();  {return data.end();  };
    // ...
}

我可以使用[] 运算符直接获取和设置值,但我希望能够使用基于范围的循环,例如

// ...
myClass<float> foo;
// ...
std::vector<int> indices (3);
indices[0] = 3;
indices[1] = 6;
indices[2] = 10;
// ...
foo[indices] = std::vector<float> (3, 0.47);

for (auto& fval : foo[indices]) { /* do stuff*/}

根据我收集到的信息,我需要advance( InputIt&amp; it, Distance n ); 来实现我想要的,并将begin()end() 成员添加到mySubset,这将返回一个带有@987654333 的类似迭代器的类型对象@ 运算符通过查看索引向量来递增迭代器:

class myIterator {
    mySubset * sb;
    std::vector<_type> it; // myClass::data iterator
public:
    myIterator(mySubset * _sb, int pos): sb(_sb) { it = sb->mc->data.begin() + sb->idx[0]; }   ;
    myIterator& operator++() { };
    myIterator& operator!=(myIterator& _other) { };
};

//.. mySubset
myIterator begin();
myIterator end();

但目前我无法理解实现这一目标所需的实际语法是什么?

【问题讨论】:

    标签: c++ class templates vector iterator


    【解决方案1】:

    我会偷懒的。

    mySubset 上实施_type&amp; operator[](size_t).size()

    template<class C>
    struct range_for_helper{
      using self=range_for_helper;
      C* c=0;
      std::size_t i = 0;
      self(C* cin, std::size_t idx):c(cin),i(idx){}
      friend bool operator==(self lhs, self rhs){return lhs.i==rhs.i;}
      friend bool operator!=(self lhs, self rhs){return lhs.i!=rhs.i;}
      void operator++(){++i;}
      decltype(auto) operator*(){ return (*c)[i]; }
    };
    

    然后添加

    mySubset 并完成。

    它不是真正的迭代器,但对于for(:) 循环来说已经足够了。它可以扩展到一个真正的迭代器,就像我说的,懒惰的。

    还有:

    range_for_helper<mySubset> begin() const { return {this,0}; }
    range_for_helper<mySubset> end() const { return {this,size()}; }
    

    如果您的[]const 重载,则可以正常工作,这很好。

    【讨论】:

    • 很公平,似乎是一个足够简单的解决方案。但是,_type&amp; operator[](size_t) 应该如何从索引向量大小返回数据值?
    • @joaocandre 首先,const std::vector&lt;int&gt;::iterator &amp; idx 摆脱 const&amp; 那里。在任何实际使用中都无法定义行为;您将向量传递给 ctor,可能调用 begin,当 ctor 完成时,开始迭代器将过期。其次,你显然可以得到第 n 项,这就是你的operator= 必须要做的。三、(mc-&gt; data)[idx[i]].
    • “当 ctor 完成时开始迭代器过期”很好,这是有道理的,我没有意识到这一点。另外,我将 i 视为索引向量的固定大小,而不是 current 索引。
    猜你喜欢
    • 2017-11-10
    • 1970-01-01
    • 1970-01-01
    • 2015-05-19
    • 2012-09-07
    • 2020-07-14
    • 1970-01-01
    • 2017-07-25
    • 2020-01-03
    相关资源
    最近更新 更多