Как пакет параметров шаблона может иметь другие возвращаемые аргументы?

В стандартном проекте C ++ 14, [temp.param] / 11 говорит:

Если шаблон-шаблон шаблона первичного classа или шаблон псевдонима является пакетом параметров шаблона, он должен быть последним параметром шаблона.

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

template // ERROR struct Bar {}; 

Но как это работает в этом случае?

 template struct Bar; template // OK ??? struct Bar {}; 

Я вижу, что это как-то связано с тем, что он является частью шаблона classа специализации, но почему ?

В правиле четко указано, что оно применяется к шаблону первичного classа. Означает ли это, что правила изменяются для специализаций?

Я попытался найти это в стандарте, но ничего не мог найти. Можете ли вы пролить свет на это.

В правиле четко указано, что оно применяется к шаблону первичного classа. Означает ли это, что правила изменяются для специализаций?

Да. Совсем просто потому, что специализация не является шаблоном первичного classа. Поэтому, если формулировка предназначена для применения ко всем объявлениям шаблонов, это будет так. Вместо этого правило очень похоже на применение только к шаблону первичного classа (… и шаблонам псевдонимов, который не может быть специализированным). Таких ограничений для специализаций нет.

Это принципиально потому, что невозможно предоставить любые аргументы шаблона после пакета параметров шаблона в основном шаблоне, но это определенно возможно сделать в специализациях. Например, вот один из способов объединения двух tuple :

 template  struct tuple_concat; template  // <== parameter pack *after* parameter pack struct tuple_concat, tuple> { using type = tuple; }; 

Это прекрасно, это работает, это полезно. Но нет никакой пользы от того, что вы можете писать такие вещи в основном шаблоне class / variable / alias, поэтому это запрещено для простоты.


Как и во всех C ++, есть, конечно, сноска. Возможно, вы могли предоставить шаблонный параметр шаблона по умолчанию, который используется для запуска смены замены. Но есть другие способы решения этой проблемы, и тогда у нас скоро появятся концепции.