Lars Kleen
Lars Kleen

Reputation: 63

Why is the template parameter losing constness?

I thought this is a very basic question but I could not find something similar.

The following code does not compile (C3668)

struct Param
{
    int a;
    int b;
};

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

struct Bar : public Foo<Param&>
{
    void doStuff (const Param &) const override
    {
        /*...*/
    }
};

It will compile after removing the const from

void doStuff (const Param &)

What am I missing here? I would expect to enforce to the const Param& in Foo::doStuff with my interface declaration. Instead it seems to be removed.

Upvotes: 6

Views: 173

Answers (3)

Hariom Singh
Hariom Singh

Reputation: 3632

Problem is not with const .Problem is with the override. Member function declared with override doesn't override a base class member

Upvotes: 1

molbdnilo
molbdnilo

Reputation: 66371

The const isn't just a text substitution, it applies to the entire type T.

If T is Param&, const T and const Param& are not equivalent; the former is the same as Param& const, which is equivalent to Param&.
It becomes more obvious if you write the less common "postfix-const" form: T const and Param const & can't be equivalent regardless of what T is.

Thus, your "override" doesn't override anything and you get a compilation error.

Upvotes: 5

NathanOliver
NathanOliver

Reputation: 180630

When you have

doStuff (const T)

it is not the same type as

doStuff (const Param &)

The first one is a constant whatever T is so in this case you have a constant reference to a T which really doesn't make sense since references cannot be rebound. In the later it is a reference to a const Param.

What you could do is change

struct Bar : public Foo<Param&>

to

struct Bar : public Foo<Param>

and then

virtual void doStuff (const T) const = 0;

to

virtual void doStuff (const T&) const = 0;

Upvotes: 1

Related Questions