Наследовать от типа const, переданного как параметр шаблона

Следующий код недействителен:

struct base {
};

struct inherit : const base {
};

Вы не можете наследовать от типа const.

Изменяется ли ситуация при использовании шаблонов? Другими словами, действительно ли этот код действителен:

struct base {
};

template<typename T>
struct inherit : T {
    using T::T;
};

int main() {
    inherit<base const>{};
}

gcc говорит, что это хорошо, но 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

Чтобы сделать clang счастливым, мне нужно сделать что-то вроде этого:

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

Какая версия верна? Или они не являются правильными, и мне нужно наследовать от std::remove_const_t<T>?

Ответы

Ответ 1

Благодаря @TC мы имеем:

Согласно [temp.param]/3:

Параметр типа, идентификатор которого не следует за многоточием, определяет его идентификатор как typedef-name (если объявлено с class или typename)... в области описания шаблона.

Таким образом, он работает точно так же, как typedef.

И затем [class.name]/5:

Если имя typedef, которое называет класс класса cv, используется там, где требуется имя класса, cv-квалификаторы игнорируются.

Следовательно, GCC прав, const должен быть разделен при наследовании от T, так как в этом месте требуется имя класса, а также при using T::T; наследование конструкторов.