【问题标题】:Abstract iterator for underlying collections底层集合的抽象迭代器
【发布时间】:2012-11-20 04:13:50
【问题描述】:

所以基本上我想做的是有一个纯虚方法将迭代器返回到具体类型的任意集合,例如在伪代码中:

virtual Iterator<T> getIterator() const = 0;

这个类的用户实际上并不关心子类使用什么实现。可以是集合、向量、列表、数组等。

我知道std::iterator 类,但我找不到正确指定它以便使用简单向量的方法。

virtual std::iterator<std::random_access_iterator_tag,T> getIterator() const = 0;

myVector.begin() // compilation error in implementation

const T 定义std::iterator 作为类型参数也没有奏效。我还尝试离开T,而是将指针和引用类型定义为const T*const T&amp;

通过查看std::vector 实现,我发现std::vector::const_iterator 实际上派生自_Iterator012,派生自_Iterator_base

我真的很烦,没有任何方法可以处理 std 中的任意集合。 将我的类实现为 &lt;algorithm&gt; 中的模板对我来说不是一个选择,原因有两个:

  • 无法控制实际值类型
  • 我只是不想让我的类模板使我的设计变得复杂,并降低灵活性。

使用的类型参数T只是为了演示,实际上这是一个具体的类型。

【问题讨论】:

  • This article 可能有用。
  • 正是模板的用途和标准库使用它们。它们只会让您的代码更加灵活!
  • 所以你想要模板,而不使用模板,这让你很困扰,除了模板的巨大特性之外,C++ 不支持模板。是的,你可能在这里有所收获。
  • @LightnessRacesinOrbit 请留下这个问题。我只是不想无缘无故地与一个讽刺的人争论。一方面:我没有看到解释我的整个架构的意义,只是为了证明模板对我来说是没有选择的。在我的具体情况下,我不想使用它们,忍受它。没有人能提出具体的解决方案而不是讨论范式吗?
  • 如果您不介意动态分配,您可以为您的值类型创建一个简单的类型擦除迭代器。

标签: c++ c++-standard-library


【解决方案1】:

这是使用类型擦除的基本且非常基本的骨架方法。不过,您必须填写 很多 缺失的详细信息!

#include <memory>

template <typename T>
class TEIterator
{
    struct TEImplBase
    {
        virtual ~TEImplBase() { }
        virtual std::unique_ptr<TEImplBase> clone() const = 0;
        virtual void increment() = 0;
        virtual T & getValue() = 0;
        T * getPointer() { return std::addressof(getValue()); }
    };

    template <typename Iter>
    struct TEImpl
    {
        Iter iter;

        TEImpl(Iter i) : iter(i) { }

        virtual T & getValue()
        { return *iter; }

        virtual std::unique_ptr<TEImplBase> clone() const
        { return std::unique_ptr<TEImplBase>(new TEImpl<Iter>(*this)); }

        virtual void increment()
        { ++iter; }
    };

    std::unique_ptr<TEImplBase> impl;

public:

    template <typename T>
    TEClass(T && x)
    : impl(new TEImpl<typename std::decay<T>::type>(std::forward<T>(x)))
    {
    }

    TEClass(TEClass && rhs) = default;

    TEClass(TEClass const & rhs) : impl(rhs.impl.clone()) { }

    TEIterator & operator++()
    {
        impl->increment();
        return *this;
    }

    T & operator*() { return impl->getValue(); }
    T * operator->() { return impl->getPointer(); }
};

用法:

std::vector<int> v;
std::deque<int> dq;

TEIterator<int> a = v.begin(), b = dq.end();

【讨论】:

  • 注解:有些人更慷慨地提倡类型擦除,因为它为多态概念提供了严格的值语义。如您所见,您需要从有效负载类中提取相关行为的样板代码。我认为,有一个提议的 Boost 库可以系统地制作这些包装类。
  • 我会推荐使用 boost 迭代器助手。在里面粘贴一个类型擦除的 pImpl 并实现所需的方法。
【解决方案2】:

如果要使用虚方法,则不能使用任意返回值。您可以做的是定义一个基类,它是迭代器的包装器,以及该包装器类的子类。

但即便如此,您也必须将自己限制在最小的公分母上,因为 C++ 标准库中有多个迭代器类。

所以,AFAICS,如果不使用模板,这种带有任意迭代器的方法实际上是不可行的。

【讨论】:

  • 一个简单的多态类不太好,因为迭代器需要按值传递。
  • @KerrekSB 是的,但是......如果你有一个带有虚拟方法的基类,而这就是 OP 所拥有的,那么就没有办法返回任意类型。否 if 或 when 或类型擦除。
猜你喜欢
  • 2014-05-24
  • 1970-01-01
  • 2021-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-29
  • 2012-07-07
  • 1970-01-01
相关资源
最近更新 更多