Вернуть ref для итератора, но const_ref для const_iterator, используя boost :: iterator_facade & lt; & gt ;?

У меня есть такой класс,

template <typename Node>
class BSTIteratorBase : public boost::iterator_facade<
BSTIteratorBase<Node>,
typename Node::value_type,
boost::forward_traversal_tag
>
{ ...
value_type& dereference() const
{ return const_cast<value_type&>( nodePtr_->value_ ); } // Ouch! const_iterator may modify
... };

value_type не зависит от константность из BSTNode учебный класс. Вот почему я должен был сохранить const_cast<value_type&>() часть. Как я могу убедиться, что const_iterator вернуть const_ref но iterator возвращает модифицируемый ref? Вот соответствующие typedefs,

template <typename T>
class BinarySearchTree
{
public:
typedef T                                   value_type;
typedef T&                                  reference;
typedef const T&                            const_reference;
typedef BSTNode<T>                          node_type;
typedef BSTNode<T>&                         node_reference;
typedef BSTNode<T>*                         node_pointer;
typedef BSTIteratorBase<BSTNode<T>>         iterator;
typedef BSTIteratorBase<const BSTNode<T>>   const_iterator;

И класс узла,

template <typename T>
class BSTNode
{
public:
typedef T           value_type;
typedef T&          reference;
typedef const T&    const_reference;
typedef BSTNode     node_type;
typedef BSTNode*    node_pointer;

// ctors, dtor

private:
template <class> friend class BSTIteratorBase;
template <class> friend class BinarySearchTree;

T value_;
node_pointer leftPtr_;
node_pointer rightPtr_;
};

1

Решение

Вы можете использовать metafunction что составляет value_type если его включающий тип — const:

template<class T>
struct ValueTypeOf {
typedef typename T::value_type type;
};

template<class T>
struct ValueTypeOf<T const> {
typedef typename T::value_type const type;
};

template <typename Node>
class BSTIteratorBase : public boost::iterator_facade<
BSTIteratorBase<Node>,
typename ValueTypeOf<Node>::type,
boost::forward_traversal_tag
>
// ...
0

Другие решения

Я был бы склонен написать

typedef BSTIteratorBase<BSTNode<T>>               iterator;
typedef BSTIteratorBase<const BSTNode<const T>>   const_iterator;
^-- note extra const

Обратите внимание, что это красиво отражает T ** -> const T *const * преобразование.

0