Я пишу контейнерный класс в стиле STL. В настоящее время я поддерживаю константные и неконстантные итераторы, используя один класс со следующей идиомой:
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_hint
или же emplace_hint
должен взять const_iterator
параметры в качестве входных данных, но мне нужно определить неявное преобразование из iterator
в const_iterator
для того, чтобы работать так, как ожидал пользователь.
Я уверен, что все должно быть в порядке, чтобы неявно преобразовать из const iterator
к const_iterator
, но я не уверен синтаксически, как это сделать. Для меня также было бы важно иметь какое-то условие для шаблона (или другого механизма), которое предотвращает const_iterator
от преобразования в iterator
,
Как определить такое преобразование?
Есть два способа написать неявное преобразование.
const_iterator
это занимает iterator
,iterator
который превращается в const_iterator
,В этом случае самый простой способ — написать функцию преобразования:
operator TreeIterator<T, true>() const { return /* ... */; }
Эта функция будет существовать как в TreeIterator<T, true>
а также TreeIterator<T, false>
, но никогда не будет использоваться, если объект уже TreeIterator<T, true>
, Обратное преобразование просто невозможно, потому что для него ничего не написано.