【问题标题】:how to define implicit conversion from custom iterator to custom const_iterator如何定义从自定义迭代器到自定义 const_iterator 的隐式转换
【发布时间】:2015-02-19 16:28:04
【问题描述】:

我正在编写一个 STL 风格的“树”容器类。我目前使用具有以下习语的单个类支持 const 和非 const 迭代器:

template<typename T>
class Tree
{
public:

    using iterator = TreeIterator<T, false>;                                                        
    using const_iterator = TreeIterator<T, true>;

    // ...
};

TreeIterator 是这样的:

template <typename T, bool is_const_iterator/* = true*/>
class TreeIterator : public std::iterator<std::forward_iterator_tag, T>
{    
public:

    // TreeNodePointer is either a const or non-const pointer depending on the template parameter.
    typedef typename std::conditional<is_const_iterator, const TreeNode<T>*, TreeNode<T>*>::type TreeNodePointer;

    // All the iterator interface and typedefs...

private:

    TreeNodePointer m_pointer;    // internal pointer.
};

问题是,为了保持我的“STL 风格”,insert_hintemplace_hint 之类的操作应该将const_iterator 参数作为输入,但我需要定义从iteratorconst_iterator 的隐式转换按照用户的预期工作。

我很确定从 const iterator 隐式转换为 const_iterator 应该没问题,但我不确定在语法上如何做到这一点。对我来说,在模板(或其他机制)上设置某种条件来阻止 const_iterator 转换为 iterator 也很重要。

如何定义这样的转换?

【问题讨论】:

    标签: c++ c++11 stl iterator const-iterator


    【解决方案1】:

    有两种方法可以编写隐式转换。

    1. const_iterator 编写一个转换构造函数,它采用iterator
    2. iterator 编写一个转换函数,将其转换为const_iterator

    在这种情况下,最简单的方法可能是写一个转换函数:

    operator TreeIterator<T, true>() const { return /* ... */; }
    

    这个函数在TreeIterator&lt;T, true&gt;TreeIterator&lt;T, false&gt; 中都存在,但如果对象已经是TreeIterator&lt;T, true&gt;,则永远不会实际使用。相反的转换是不可能的,因为没有为它写任何东西。

    【讨论】:

    • 还有第三种可能性:让iterator 派生自const_iterator。 (我不确定这是否真的是一个好主意,但我已经看到它在过去使用过。)
    • @JamesKanze 听起来……很乱。不使用专业化也很难在这里写。
    • @T.C.所以这实际上正是我所做的:operator TreeIterator&lt;T, true&gt;() const { return TreeIterator&lt;T,true&gt;(*this); }。但是,这似乎不起作用,因为我仍然收到编译错误cannot convert argument 1 from 'TreeIterator&lt;T,false&gt;' to 'TreeIterator&lt;T,true&gt;。我认为我缺少的链接是return /*...*/ 部分。
    • @NicolasHolthaus 好吧,您仍然需要编写一些构造 const_iterator 的内容来指向 iterator 指向的同一节点,可能使用 m_pointer。我不知道您是如何编写 TreeIterator 构造函数的,但应该有一个接受节点指针或类似内容的构造函数,不是吗?
    • @T.C.这也不是我直观地选择的解决方案。但这可能取决于迭代器:我的总是如此简单,以至于在 const 和非 const 版本之间重复的少量代码是微不足道的。如果它变得更复杂,继承解决方案可能是最简单的,尽管它需要 const_casting。
    猜你喜欢
    • 2016-04-05
    • 2020-01-03
    • 2013-02-17
    • 2021-03-19
    • 2015-02-04
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    相关资源
    最近更新 更多