5

好的,所以我现在有两个(完全不相关的、不同的项目)类使用迭代器。一个具有iterator并按reverse_iterator预期工作,另一个当前具有iterator和半损坏const_iterator(具体来说,因为 const_iterator 派生自迭代器,所以代码LinkedList<int>::iterator i = const_list.begin()是有效的并且允许您修改 const 定义的列表......)。
我打算将所有四种类型都添加到这个类中......如果可以的话。

我将如何继续最小化复制/粘贴代码并仅更改返回类型?base_iterator创建一个喜欢继承的基类?创建一个iteratororconst_iterator并从中继承?从一些 std:: 类继承?如果这些案例中的任何一个是“最佳”方法,那么哪些代码在哪里?
也许没有一个替代品是好的?我在这里很迷茫,找不到太多参考资料。

任何建议都值得赞赏,但请记住,我是该主题的新手(通常是迭代器和 C++,尤其是 OOP)。我尝试研究 GCC 附带的头文件,但徒劳无功——它们并不完全是我正在寻找的教程。

4

6 回答 6

3

它实际上非常简单。

首先,看一下Boost.Iterator库。

第二:您需要声明一个与此类似的基类(在示例中很好地解释了如何进行)。

template <class Value>
class BaseIterator: boost::iterator_adaptor< ... > {};

您执行操作以将指针移动到那里。请注意,由于它是对现有迭代器的改编,因此您只需几笔即可实现它。这真的令人印象深刻。

第三,您只需使用 const 和非 const 版本对其进行 typedef :

typedef BaseIterator<Value> iterator;
typedef BaseIterator<const Value> const_iterator;

该库明确向您展示了如何使const_iterator版本可从iterator版本构造。

第四,对于反向的东西,有一个特殊的reverse_iterator对象,它建立在一个常规的迭代器上并向后移动:)

总而言之,这是一种在自定义类上定义迭代器的非常优雅且功能齐全的方式。

我经常编写自己的容器适配器,这与 DRY 无关,而不仅仅是为自己节省一些打字时间!

于 2009-11-23T08:15:16.463 回答
3

有时,一揽子应用所谓的 DRY 规则(不要重复自己,对于那些不熟悉的人)并不是最好的方法。特别是如果您不熟悉该语言(C++ 和迭代器)和 OOP 本身(方法),那么尝试尽量减少您现在需要编写的代码量几乎没有什么好处。

我将为每个迭代器使用适当的代码来实现这两个迭代器。也许在您对语言、工具和技术有了更多经验之后,回头看看是否可以通过分解通用代码来减少代码量。

于 2009-11-21T20:22:27.903 回答
1

使迭代器从 const_iterator 派生而不是相反。适当使用const_cast(作为实现细节,不向用户公开)。这在“迭代器是 const_iterators”的简单案例和模型中非常有效。

当这开始需要在您的代码中进行澄清注释时,请编写单独的类。您可以使用本地化宏为您生成类似的代码,以避免重复逻辑:

struct Container {
#define G(This) \
This& operator++() { ++_internal_member; return *this; } \
This operator++(int) { This copy (*this); ++*this; return copy; }

  struct iterator {
    G(iterator)
  };
  struct const_iterator {
    G(const_iterator)
    const_iterator(iterator); // and other const_iterator specific code
  };
#undef G
};

宏的作用域/本地化很重要,当然,只有在它确实对您有帮助时才使用它——如果它导致您的代码可读性降低,请明确键入它。

关于反向迭代器:在许多情况下,您可以使用std::reverse_iterator包装“普通”迭代器,而不是重写它们。

struct Container {
  struct iterator {/*...*/};
  struct const_iterator {/*...*/};

  typedef std::reverse_iterator<iterator> reverse_iterator;
  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
};
于 2009-11-21T21:19:48.270 回答
0

一旦我使用了以下方法:

  1. 制作一个模板类 common_iterator
  2. 为“iterator”和“const_iterator”添加类型定义
  3. 向“common_iterator”添加一个采用“迭代器”类型的构造函数

对于“迭代器”,附加构造函数将替换默认的复制构造函数,在我的情况下,它相当于默认的复制构造函数。

对于“const_iterator”,它将是一个额外的构造函数,允许从“iterator”构造“const_iterator”

于 2009-11-21T21:57:19.617 回答
0

LinkedList<int>::iterator i = const_list.begin()你的开始方法是什么样的?通过研究 STL,您可以看到容器定义了两个具有以下签名的此类方法:

const_iterator begin() const;
iterator begin();

iterator从一个限定为 const 的对象中获取 a 应该没有问题。我不认为 DRY 在这里适用。

于 2009-11-21T21:13:26.037 回答
0

maxim1000 建议的更具体版本:

#include <type_traits>

template<typename Container, bool forward>
class iterator_base
{
public:
    using value_type =
        typename std::conditional<std::is_const<Container>::value,
                                 const typename Container::value_type,
                                 typename Container::value_type>::type;

    iterator_base() { }

    // For conversions from iterator to const_iterator.
    template<typename U>
    iterator_base(const iterator_base<U, forward>& other)
    : c(other.c)
    {
        // ....
    }

    value_type& operator*() const
    {
        // ...
    }

    iterator_base& operator++()
    {
        if (forward)
        {
            // ...
        }
        else
        {
            // ...
        }
    }

    iterator_base& operator++(int)
    {
        iterator_base copy(*this);
        ++*this;
        return copy;
    }

private:
    Container* c = nullptr;
    // ...
};

using iterator = iterator_base<self_type, true>;
using const_iterator = iterator_base<const self_type, true>;

using reverse_iterator = iterator_base<self_type, false>;
using const_reverse_iterator = iterator_base<const self_type, false>;
于 2017-08-21T18:28:35.523 回答