c++overloadingconstantstemplate-instantiation

Is it possible to define both const and regular version of the function with a single definition? (using templates, auto, decltype, etc)


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?


Solution

  • 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;
    }