Что такое шаблон <> шаблон <> синтаксис в контексте шаблона-псевдонима?

(Этот вопрос не касается аргументов шаблона шаблона.)

Я только что обнаружил, что GCC компилирует такой код

template <typename A, typename B>
struct P {};

template <typename A>
template <typename B>
using Q = P<A, B>;

где Q - двукратно оформленное имя.

Но я не могу использовать это. Когда я пишу Q<short><long>, я получаю

template_template.cpp:10:5: error: ‘Q<short int>’ is not a template
     Q<short><long>{};
     ^~~~~~~~
template_template.cpp:10:20: error: invalid use of incomplete type ‘Q<short int>’
     Q<short><long>{};
                    ^
template_template.cpp:2:8: note: declaration of ‘Q<short int>’
 struct P {};

Почему скомпилирован первый фрагмент?

Есть ли синтаксис, чтобы убедить компилятор, что Q<short> является фактически шаблоном?

//GCC 6.3.0

Ответы

Ответ 1

Стандарт С++ 14 говорит в 14p1:

Объявление в объявлении шаблона должно быть - объявить или определить функцию, класс или переменную, или
- определить функцию-член, класс-член, перечисление элемента или статический элемент данных шаблона класса или класса, вложенного в шаблон класса, или
- определить шаблон элемента шаблона класса или класса, или
- быть объявлением alias

Здесь объявление в объявлении шаблона не является ничем из вышеперечисленного (это другое объявление-шаблон, которое содержит декларацию alias), поэтому код недействителен.

Соответствующие части грамматики:

шаблон-декларация:
    шаблон < template-parameter-list > объявление

псевдоним декларации:
    с использованием идентификатора атрибута-спецификатора-seq opt= type-id;

где объявление может быть объявлением шаблона, декларацией псевдонима или другими типами объявлений.

Обратите внимание, что сама грамматика принимает данный код, но дополнительные ограничения в тексте выше делают его недействительным.