Suppose that I am writing an iterator and const_iterator for singly linked list.
Suppose that I have a following classes:
template <typename T>
struct Node
{
T value;
Node* next;
}
template <typename T>
struct NodePtr
{
private:
Node<T>* node;
public:
T& operator*() { return node->value; }
const T& operator*() const { return node->value; }
// Ommitted increment, comparison and so on...
}
class Iterator<T, bool isConst>
{
private: NodePtr<T> nodePtr;
using Reference = std::conditional_t<isConst, const T&, T&>;
Reference operator*() { return *nodePtr; }
const Reference operator*() const { return *nodePtr; }
// Ommited
}
My question is whether it is possible somehow to replace the lines
Reference operator*() { return node->value; }
const Reference operator*() const { return node->value; }
with a single definition (perhaps using the template argument isConst) and have the const specifier deduced by the compiler? I want to have * to be const T& operator*() const when isConst = true and have both versions when isConst = false. Is it possible? If it is - then how to do it?
I don't think there is a way to write the function only once. Most things you can do with auto and templates but the problem is the const
specifier for the function itself. I know of no way to make that in any form conditional. You could make it always const and then the nodePtr
mutable but that kind of defeats the point of the whole thing. What you can do is deactivate the non-const overload for the const_iter
by doing the following
template<bool tmp = isConst, std::enable_if_t<!tmp, char> = 0> // you need the tmp so that the enable_if is dependent
Reference operator*() {
return *nodePtr;
}