对于使用虚拟接口对象的范围(c ++ 11)

Ama*_*eus 2 c++ c++11

我正在编程接口,我想以一种通用的方式对其内容进行交互.所以,一般来说,我的接口都有这样的原型:

class Interface
{
public:
  class Iterator;
  virtual Interface::Iterator* begin() = 0;
  virtual Interface::Iterator* end() = 0;  

  class Iterator
  {
  public:
    virtual const Iterator* operator++() = 0;
    virtual bool operator!=(const Iterator& i) = 0;
  };
};
Run Code Online (Sandbox Code Playgroud)

和吼叫,是一个简单的专业化的例子:

class Derived : public Interface
{
public:
  Derived() : array {2, 0, 1, 5, 4, 3} {};
  Iterator* begin() { return new Derived::IterDerived(0);};
  Iterator* end() { return new Derived::IterDerived(6);};

  int array[6];

public:
  class IterDerived : public Interface::Iterator
  {
  public:
    IterDerived(int i) {pos = i;};
    IterDerived(IterDerived&& i) {pos = i.pos;};

    const Interface::Iterator* operator++() override { ++pos; return this;};
    bool operator!=(const Interface::Iterator& i) { return pos != dynamic_cast<const     Derived::IterDerived&>(i).pos;};
    int position() { return pos;};

  private:
    int pos;
  };
};
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.现在,我想编写一段代码,允许我使用new for range来迭代其内容,如新标准(c ++ 11)中所指定的那样.请注意,在实际界面中,我将提供getter方法,因此使用dynamic_cast是不必要的.即:

int main()
{
  Interface *a = new Derived();

  for(auto i : a) 
    std::cout << dynamic_cast<Derived*>(a)->array[dynamic_cast<Derived::IterDerived*>(i.get())->position()] << " ";
  std::cout << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

但是这段代码没有编译.为了编译,我需要以下列形式使用宏:

#define FOR_ITERATOR(iter, object)                  \
  for(std::unique_ptr<Interface::Iterator> iter((object)->begin()), \
    iter##end((object)->end());                 \
      *iter != *(iter##end); ++(*iter))
Run Code Online (Sandbox Code Playgroud)

在范围的地方.有没有机会使用新的语句范围,还是我必须使用这种宏?

Chr*_*odd 6

当你说:

Interface *a = new Derived();
for(auto i : a) 
Run Code Online (Sandbox Code Playgroud)

a是指针,迭代指针实际上没有任何意义.你可能想要:

for (auto i : *a)
Run Code Online (Sandbox Code Playgroud)

也就是说,迭代a指向的对象.

这可能仍然无效,因为你Interface::beginInterface::end方法返回的是一个Interface::Iterator *而不是一个Interface::Iterator,这是无稽之谈.

您似乎希望能够使用子类Interface::Iterator来迭代派生类,但这不起作用,因为auto需要能够为i它构建的对象(及其关联的迭代器)找出静态类型.

如果你想做这样的事情,你需要让你的迭代器对象封装一个指针,该指针可以被Derived子类化,同时保持迭代器类本身的固定.就像是:

class Interface
{
public:
  class Iterator;
  virtual Interface::Iterator begin() = 0;
  virtual Interface::Iterator end() = 0;  

protected:
  class IteratorImpl {
  public:
    virtual IteratorImpl &operator++() = 0;
    virtual bool operator!=(const Iterator& i) = 0;
    virtual IteratorImpl *clone() = 0;
  };
};

public:
  class Iterator {
  protected:
    class IteratorImpl *impl;
  public:
    Iterator(IteratorImpl *a) : impl(a) {}
    Iterator(iterator &a) : impl(a.impl->clone()) {}
    Iterator &operator++() { ++*rep; return this; }
        :
Run Code Online (Sandbox Code Playgroud)

然后你从中得到这个

class Derived : Interface {
  class IteratorImpl : public Interface::IteratorImpl {
       :
  };
public:
  Iterator begin() { return Iterator(new IteratorImpl( ...
Run Code Online (Sandbox Code Playgroud)

当然,您需要确保添加所有必需的析构函数,赋值运算符,解引用运算符等.

这可能还需要模仿应该包含在您实际迭代的任何类型中的类型.