【发布时间】:2020-02-27 20:49:03
【问题描述】:
在实现自定义容器时,我需要实现迭代器。当然,我不想为 const 和非 const 迭代器编写两次代码。我发现this question 详细说明了这样的可能实现:
template<class T>
class ContainerIterator {
using pointer = T*;
using reference = T&;
...
};
template<class T>
class Container {
using iterator_type = ContainerIterator<T>;
using const_iterator_type = ContainerIterator<const T>;
}
但我也发现了这个使用模板参数的this question:
template<class T, bool IsConst>
class ContainerIterator {
using pointer = std::conditional_t<IsConst, const T*, T*>;
using reference = std::conditional_t<IsConst, const T&, T&>;
...
};
template<class T>
class Container {
using iterator_type = ContainerIterator<T, false>;
using const_iterator_type = ContainerIterator<T, true>;
}
第一个解决方案似乎更容易,但答案来自 2010 年。 在做了一些研究之后,似乎第一个版本没有被广泛使用,但我不明白为什么。我觉得我错过了第一个版本的一些明显缺陷。
所以问题变成了:
第一个版本有问题吗?
如果不是,为什么版本 #2 似乎是 c++17 中的首选方式?或者为什么我应该更喜欢一个?
另外,是的,使用
const_cast 或简单地复制整个代码将是一种解决方案。但我不喜欢这两个。
【问题讨论】:
-
不是具体问题的答案,但请注意
boost::iterator_facade和boost::iterator_adaptor有助于创建迭代器类型所需的大量样板。 -
另外,除了“在 C++17 中”,这个问题怎么不是你链接到的那个的重复?
-
@NicolBolas 感谢您的澄清,我编辑了我的代码以反映这一点。我实际上是从
std::array::iterator的实现中得到这个的,并认为它会像这样命名,只在最后出现在智能感知中。作为一种“几乎隐藏”的类之类的。 -
@NicolBolas 这个问题更多地针对原因,为什么应该首选第二种实现(应该吗?)。因为我看不到,为什么第一个解决方案在 c++17 中会变得无效或不切实际。