是否可以重用通常的迭代器来构建常量迭代器?
Is it possible to reuse usual iterator to build const iterator?
研究
我找到了这个古老的答案。我想知道解决方案是否仍然有效,或者是否有新的、更有效的方法可以做到这一点。
背景
假设我有一个像下面这样的迭代器(细节并不重要,只是它很大(:
class inorder_iterator : public std::iterator<std::forward_iterator_tag, token>
{
friend syntax_tree;
node* current_node;
std::stack<node*> prev_nodes;
//std::stack<node*> visited_nodes;
std::map<node*, bool> visited;
public:
inorder_iterator();
inorder_iterator& operator++();
inorder_iterator operator++(int);
token& operator*();
const token& operator*() const;
token* operator->();
const token* operator->() const;
friend bool operator==(const inorder_iterator lhs, const inorder_iterator rhs);
friend bool operator!=(const inorder_iterator lhs, const inorder_iterator rhs);
private:
inorder_iterator(node* current);
node* find_leftmost_node(node* from);
};
问题
成员函数声明的实现大小合理,但我想重用当前的迭代器以减少代码重复。
想法
想到的第一个想法是在node
类型上进行模板化,这样我就可以传递const node
使其成为 const 迭代器,但这听起来很可疑
template <typename Node>
//replace every occurrence of node with Node
// and use decltype(node.tk) instead of token everywhere
我也不确定这种const
的使用是否是"const 属于实现细节"的情况之一。
模板可能是避免代码重复的唯一方法。但我不会让类型参数保持打开状态。我只需使用馈送到std::conditional
的布尔参数来确定类型:
template<bool IsConst> class iter_impl {
using value_type = std::conditional_t<IsConst, Node const, Node>;
};
然后,容器的两种迭代器类型可以是几个别名,或者如果你想要真正不同的类型,也可以是几个从模板继承的类。这样:
struct const_iterator : iter_impl<true> {};
struct iterator : iter_impl<false> {};
使用两个新类的好处是,您可以为const_iterator
定义一个转换构造函数,允许它从非常量迭代器构建。这类似于标准库的行为。
我也不确定 const 的这种使用是否是"const 属于实现细节"的情况之一。
您使用const Node
的事实确实是一个实现细节。但只要它为您提供记录的类型行为(容器的 const 成员的迭代器(,我就不会对此强调太多。
您可以安全地定义类模板template< typename value_type > iterator
按值类型(const
或非const
(参数化,并将运算符转换为const
版本(即operator interator< value_type const > () const
(:
template< typename type >
struct node
: node_base
{
union { type value; };
node() noexcept { ; }
node(node const &) = delete;
node(node &&) = delete;
void operator = (node const &) = delete;
void operator = (node &&) = delete;
~node() { ; }
type * pointer() noexcept { return &value; }
};
template< typename type >
struct tree_iterator
{
using value_type = type;
using reference = type &;
using pointer = type *;
using iterator_category = std::bidirectional_iterator_tag;
using difference_type = std::ptrdiff_t;
using node_type = node< value_type >;
using node_pointer = node_type *;
base_pointer p = nullptr;
pointer operator -> () const noexcept { return node_pointer(p)->pointer(); }
reference operator * () const noexcept { return *operator -> (); }
tree_iterator & operator ++ () noexcept { p = increment(p); return *this; }
tree_iterator operator ++ (int) noexcept { return {std::exchange(p, increment(p))}; }
tree_iterator & operator -- () noexcept { p = decrement(p); return *this; }
tree_iterator operator -- (int) noexcept { return {std::exchange(p, decrement(p))}; }
bool operator == (tree_iterator const & it) const noexcept { return p == it.p; }
bool operator != (tree_iterator const & it) const noexcept { return !operator == (it); }
operator tree_iterator< type const > () const { return {p}; }
};
在using const_iterator = iterator< value_type const >;
,后者变成了no-op,只能被有意地调用(即使用语法it.template operator iterator< value_type const > ()
(。
代码是从这里给出的 - 重写libstdc++的红黑树。
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 如何在c++迭代器类型中包装std::chrono
- 集合上的输出迭代器:assign和increment迭代器
- Boost Spirit,获取迭代器内部语义动作
- 对于set上的循环-获取next元素迭代器
- 为什么output_editor Concept不需要output_e迭代器标记
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 使用迭代器时如何访问对象在向量中的位置?
- C++如何为向量向量构建迭代器
- 是否可以重用通常的迭代器来构建常量迭代器?
- 如何以链式方式在两个容器上构建迭代器
- 为链接列表构建迭代器类(错误:无匹配的构造函数以初始化)
- 提升 ASIO 1.66 示例无法构建 - async_connect() 需要单个迭代器无法在 VS2010 上链接
- Qt:为模板(映射、列表、集合等)构建一个可变迭代器
- 使用迭代器构建 QVector 对象
- 如何为我在C++中创建的对象构建迭代器
- 使用迭代器从double-for循环构建向量
- 使用zip迭代器调用boost::compute::sort()会导致构建错误