简体   繁体   English

如何从 C++ 迭代器类继承?

[英]How to inherit from c++ iterator class?

Below I depict the general structure of my code:下面我描述了我的代码的一般结构:

class OperandIterator : public std::iterator<std::input_iterator_tag, pOpReference>
{
public:
    OperandIterator(...)...
    OperandIterator & operator++();  // also calls to advance()
    OperandIterator operator++(int); // also calls to advance() 
    bool operator==(const OperandIterator & other) const;
    bool operator!=(const OperandIterator & other) const;
    pOpReference operator*();
protected:
    virtual void advance();
}

class OperandSpecialIterator : public OperandIterator 
{
public:
     ...    
private:
    void advance() override; // this is the only diffrence between the classes
}

class TraversalPattern
{
 public:
       TraversalPattern(Operand op, Order order, bool specialTraversal);
       OperandIterator begin() { return specialTraversal ? OperandSpecialIterator(...) : OperanInerator(...); }
}


// somewhere
TraversalPattern p(...specialTraversal=ture);
OperandIterator iter = p.begin();
it++;

Even though begin() function returns OperandSpecialIterator, when it++ performed the advance function that is being called is the advance function of OperandIterator.即使begin()函数返回OperandSpecialIterator,当it++执行时,被调用的advance函数是OperandIterator的advance函数。 The problem is that begin() can't return a reference.问题是 begin() 不能返回引用。 The question is: Can begin function return iterators of different types?问题是: begin 函数可以返回不同类型的迭代器吗?

What you are asking is not possible.你问的是不可能的。 The begin() function cannot return different types depending on a runtime value. begin()函数不能根据运行时值返回不同的类型。 What you could do, is implement something like a VariantIterator that can hold different types of operators in an std::variant (C++17) and forwards the iterator operations to the currently held iterator.你可以做的是实现类似VariantIterator东西,它可以在std::variant (C++17) 中保存不同类型的运算符,并将迭代器操作转发到当前保存的迭代器。

For this simple case, I personally would do the advancing by passing a function pointer to my Iterator:对于这个简单的情况,我个人会通过将函数指针传递给我的迭代器来进行推进:

class OperandIterator; // forward declaration

namespace advancers { // Forward declarations since definition only works, 
      // when OperandIterator is defined. You can make this easier by making
      // these methods static in the class. I declare them forward to be able
      // to use them as defaults in OperandIterator.
  void advance_normally(OperandIterator& it);

  void advance_specially(OperandIterator &it);
} // End namespace advancers

class OperandIterator : public std::iterator<std::input_iterator_tag, pOpReference>
{
public:
  OperandIterator() = default;
  OperandIterator(void (*advanc_fnc)(OperandIterator&)) : advancer(advanc_fnc) {}
  OperandIterator & operator++();  // also calls advancer with *this
  OperandIterator operator++(int); // also calls advancer with *this 
private:
  const void (*advancer)(OperandIterator&) = &advancers::advance_normally;
}

namespace advancers { // Definitions
  void advance_normally(OperandIterator& it) {
    it++;
  }

  void advance_specially(OperandIterator &it) {
    // Something else
  }
} // End namespace advancers



OperandIterator make_special() {
  return OperandIterator(&advancers::advance_specially);
}

class TraversalPattern
{
 public:
       TraversalPattern(Operand op, Order order, bool specialTraversal);
       OperandIterator begin() { return specialTraversal ? OperandSpecialIterator() : make_special(); }
}


// somewhere
TraversalPattern p(...specialTraversal=ture);
OperandIterator iter = p.begin();
it++;

The nice thing about this is, that you can easily add more versions of advancing and even make them in place with a lambda.这样做的好处是,您可以轻松添加更多版本的推进,甚至可以使用 lambda 使它们就位。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM