2017-02-21 45 views
6

Я думал, что это очень простой вопрос, но я не мог найти что-то подобное.Почему параметр шаблона теряет константу?

Следующий код не компилируется (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 
    { 
     /*...*/ 
    } 
}; 

Он будет собирать после удаления сопзЬ из

void doStuff (const Param &) 

Что я здесь отсутствует? Я бы ожидал, что будет применен к const Param& in Foo::doStuff с моей декларацией интерфейса. Вместо этого он, кажется, удаляется.

+1

Верхний уровень const игнорируется в объявлениях функций. Кроме того, 'const T' будет означать' Param & const', а не 'const Param &'. –

ответ

5

const - это не просто замена текста, это относится ко всему типу T.

Если T is Param&, const T и const Param& не являются эквивалентными; первая такая же, как Param& const, что эквивалентно Param&.
Это становится более очевидным, если вы пишете менее распространенную форму «постфикс-const»: T const и Param const & не могут быть эквивалентными, независимо от того, что такое T.

Таким образом, ваше «переопределение» не отменяет ничего, и вы получаете ошибку компиляции.

1

Если у вас есть

doStuff (const T) 

это не тот же тип

doStuff (const Param &) 

Первый является постоянным, независимо Т ​​так что в этом случае у вас есть постоянная ссылка на Т, действительно не имеет смысла, поскольку ссылки не могут быть отскок. В дальнейшем это ссылка на const Param.

Что вы можете сделать, это изменить

struct Bar : public Foo<Param&> 

в

struct Bar : public Foo<Param> 

, а затем

virtual void doStuff (const T) const = 0; 

в

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

Проблема не с константой. Проблема с переопределением. Функция-член, объявленная с помощью переопределения, не переопределяет элемент базового класса