Question

Consider following code:

template<typename T>
struct MyTempl
{
    virtual void doStuff(const T &value) = 0;
};

struct MyImpl : MyTempl<int>
{
    void doStuff(const int &value) {}
};

struct MyPtrImpl : MyTempl<int*>
{
    void doStuff(const int* &value) {}
};

MyImpl imp1;
MyPtrImpl imp2;

This will not compile correctly: the compiler tells me that doStuff() in MyPtrImpl is pure virtual, ie. I failed to correctly override it. If I however typedef int* to something like int_ptr, and use that as the template argument for MyPtrImpl, everything works out.

Why is the compiler unable to deduct my intent without the typedef?

Was it helpful?

Solution

You didn't specify the correct parameter type of the virtual function and thus you're not overriding it. This results in an abstract class since the virtual function is pure.

When specifying a parameter of a const reference type like

void doStuff(const int & value) {}

it's actually an alternative to write

void doStuff(int const & value) {}

which should be considered the "normal" way to declare a constant reference. When read from right to left this means "a reference to constant int". Applying the same pattern to the pointer type int* results in

void doStuff(int* const & value) {}

which compiles fine. But that one can't be written in the order like above, since that would mean something different: read const int* & from right to left and you get "a reference to a pointer to a constant int".

As you mentioned it, an alternative which works with the order from above can be written if you use typedef to alias the pointer type int*:

typedef int *T;
void doStuff(const T & value) {}

which also compiles fine, since T is now seen as a single literal type not introducing the ambiguities from above. In other words, the only option for how to read const T & is "a reference to a const T, which itself is a pointer to int". It's a bit difficult to understand it intuitively, but what's not possible is to understand this as "a reference to a pointer to a constant int", since this would not have a single T in the description.

I recommend to use the keyword override if you're using a C++11 compiler in order to detect problems like this (there are scenarios in which this problem will not result into a compilation error but into unexpected behavior; for example if the virtual function was not pure):

void doStuff(int* const & value) override {}
//                               ^^^^^^^^
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top