Inc*_*ble 1 c++ code-reuse const-iterator c++14
我找到了这个老答案.我想知道解决方案是否仍然有效,或者是否有更新,更有效的方法.
让我们假设我有一个像下面这样的迭代器(细节并不重要,只是它很大):
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);
};
Run Code Online (Sandbox Code Playgroud)
成员函数声明的实现具有合理的大小,但我想重用当前的迭代器来减少代码重复.
想到的第一个想法就是在node类型上进行模板化,所以我可以通过const node使它成为const迭代器,但它听起来很腥
template <typename Node>
//replace every occurrence of node with Node
// and use decltype(node.tk) instead of token everywhere
Run Code Online (Sandbox Code Playgroud)
此外,我不确定这种使用const是否属于"const属于实现细节"的情况之一.
模板可能是避免代码重复的唯一方法.但我不会打开类型参数.我只是使用一个布尔参数,它被输入a std::conditional以确定类型:
template<bool IsConst> class iter_impl {
using value_type = std::conditional_t<IsConst, Node const, Node>;
};
Run Code Online (Sandbox Code Playgroud)
然后,容器的两个迭代器类型可以是几个别名,或者如果您想要真正的不同类型,则可以使用从模板继承的几个类.像这样:
struct const_iterator : iter_impl<true> {};
struct iterator : iter_impl<false> {};
Run Code Online (Sandbox Code Playgroud)
使用两个新类的好处是,您可以定义一个转换构造函数const_iterator,允许它从非const迭代器构建.这类似于标准库的行为.
此外,我不确定const的使用是否是"const属于实现细节"的情况之一.
您使用a的事实const Node确实是一个实现细节.但只要它给你记录的类型行为(容器的const成员的迭代器),我就不会对此过分强调.