Suppose that I have a following class
template <typename T>
struct Node { T value; Node* next; };
Often one needs to write code similar to this (let's assume that Sometype is std::string for now, although I don't think that it matters).
Node<SomeType> node = Node{ someValue, someNodePtr };
...
Node <const SomeType> constNode = node; // compile error
One way to work around is to define explicit conversion operator:
template <typename T>
struct Node
{
T value;
Node* next;
operator Node<const T>() const {
return Node<const T>{value, reinterpret_cast<Node<const T>* >(next)};
}
};
Is there a better, "proper" way to do it? 1. In general, what is the proper way to allow conversion of SomeType to SomeType except explicitly defining conversion operator? (Not in my example only). 2. If defining conversion operator is necessary, is reinterpret_cast is the proper way to do it? Or there are "cleaner" ways?
EDIT: Answers and comments were very helpful. I decided to provide more context right now. My problem is not with implementing const_iterator itself (I think that I know how to do it), but how to use same template for iterator and const_iterator. Here is what I mean
template <typename T>
struct iterator
{
iterator(Node<T>* _node) : node{ _node } {}
T& operator*() { return node->value; } // for iterator only
const T& operator*() const { return node->value; } // we need both for iterator
// for const iterator to be usable
iterator& operator++() { node = node->next; return *this; }
iterator operator++(int) { auto result = iterator{ node }; node = node->next; return result; }
bool operator==(const iterator& other) { return node == other.node; }
bool operator!=(const iterator& other) { return Node != other.node; }
private:
Node<T>* node;
};
Implementing const_iterator is essentially the same, except that T& operator*() { return node->value; }.
The initial solution is just to write two wrapper classes, one with T& operator*() and the other one without. Or use inheritance, with iterator deriving from const_iterator (which might be a good solution and has an advantage - we don't need to rewrite comparison operators for iterator and can compare iterator with const_iterator - which most often makes sense - as we check that they both point at same node).
However, I am curious how to write this without inheritance or typing same code twice. Basically, I think that some conditional template generation is needed - to have the method T& operator*() { return node->value; } generated only for iterator and not const_iterator. What is the proper way to do it? If const_iterator treated the Node* as Node*, it almost solves my problem.