Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inherit from const type passed as template parameter

Tags:

The following code is not valid:

struct base { };  struct inherit : const base { }; 

You cannot inherit from a const type.

Does the situation change when templates are involved? In other words, is this code valid:

struct base { };  template<typename T> struct inherit : T {     using T::T; };  int main() {     inherit<base const>{}; } 

gcc is says it is fine, but clang reports

<source>:6:2: error: 'const base' is not a direct base of 'inherit<const base>', cannot inherit constructors          using T::T;          ^        ~  <source>:10:2: note: in instantiation of template class 'inherit<const base>' requested here          inherit<base const>{};          ^  1 error generated.  Compiler returned: 1 

To make clang happy, I need to do something like this:

template<typename T> struct inherit : T {     using U = std::remove_const_t<T>;     using U::U; }; 

Which version is correct? Or are neither of them correct and I need to inherit from std::remove_const_t<T>?

like image 329
David Stone Avatar asked May 25 '18 17:05

David Stone


1 Answers

Thanks to @T.C. we have:

According to [temp.param]/3:

A type-parameter whose identifier does not follow an ellipsis defines its identifier to be a typedef-name (if declared with class or typename) ... in the scope of the template declaration.

So it works just like a typedef.

And then [class.name]/5:

If a typedef-name that names a cv-qualified class type is used where a class-name is required, the cv-qualifiers are ignored.

Hence GCC is right, const should be stripped when inheriting from T, since a class-name is required at that point, as well as in the using T::T; inheriting constructors declaration.

like image 182
rustyx Avatar answered Oct 10 '22 18:10

rustyx