在C ++中通过纯虚拟容器接口进行迭代

时间:2019-01-11 15:27:28

标签: c++ boost stl iterator containers

我有一个与容器差不多的纯虚拟接口,

class IContainer
{
public:
    virtual ~IContainer() = default;
    virtual Element& operator[](size_t index) = 0;
    virtual const Element& operator[](size_t index) const = 0;
    virtual size_t size() const = 0;
};

我想对循环使用范围,所以我需要定义begin()和end()。为此,我还需要定义迭代器类型。

应该不是特别难,但是在我开始编码已经存在的东西之前,我还是想知道STL或Boost中是否有可以帮助的东西。

2 个答案:

答案 0 :(得分:3)

这可能不是一个好主意,但是在这里添加for(:)循环支持相对容易。我会很小的。

我将创建一个iteroid,这是一个非迭代器,足以支持for(:)循环。这需要++!=和一元*的支持,而没有其他要求。

template<class C>
struct index_iteroid {
  decltype(auto) operator*()const {
    return (*container)[i];
  }
  index_iteroid(index_iteroid const&)=default;
  index_iteroid& operator=(index_iteroid const&)=default;
  friend bool operator==(index_iteroid const& lhs, index_iteroid const& rhs) {
    return std::tie(lhs.i, lhs.container)==std::tie(rhs.i, rhs.container);
  }
  friend bool operator!=(index_iteroid const& lhs, index_iteroid const& rhs) {
    return !(lhs==rhs);
  }
  void operator++()&{
    ++i;
  }
  index_iteroid(C* c, std::size_t in):i(in), container(c) {}
private:
  std::size_t i = 0;
  C* container = nullptr;
};

现在我们使用它:

class IContainer
{
public:
    virtual ~IContainer() = default;
    virtual Element& operator[](size_t index) = 0;
    virtual const Element& operator[](size_t index) const = 0;
    virtual size_t size() const = 0;
    index_iteroid<IContainer> begin() { return {this, 0}; }
    index_iteroid<IContainer> end() { return {this, size()}; }
    index_iteroid<IContainer const> begin() const { return {this, 0}; }
    index_iteroid<IContainer const> end() const { return {this, size()}; }
};

就在那里。

void test( IContainer* cont ) {
  if (!cont) return;
  for(Element& e : *cont) {
    // code
  }
}

请原谅任何错别字。

现在,一个完整的迭代器所需要的代码大约是我的iteroid的2-3倍,但是没有什么棘手的事情,大部分只是令人讨厌的样板代码。


该标准对您没有太大帮助。为了提高效率,您可以将计数迭代器与函数校准迭代器/生成器组合在一起,并使函数调用使用[]。如果要将iteroid升级为迭代器,Boost还提供了一些实用程序,可以减少编写完整迭代器的过程。

答案 1 :(得分:1)

C ++不会像这样执行“接口”。惯用的方式是将IContainer的(潜在)客户端改为在容器类型上进行模板化并仅调用values[index],或在迭代器类型上进行模板化并进行类似*(first + offset)的调用。 / p>

在C ++ 20中,您将能够编写Container Concept,其行为有点像接口定义,但是您已经可以将概念表达为已记录的需求。

如果您想使用类型擦除的随机访问“容器”,则可以使用boost::any_range<Element, boost::random_access_traversal_tag>