Как пакет параметров шаблона может иметь другие конечные аргументы? - PullRequest
0 голосов
/ 05 сентября 2018

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

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

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

template< typename ...Args, void(*f)(Args...) > // ERROR
struct Bar
{};

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

template< typename F, F >
struct Bar;

template< typename ...Args, void(*f)(Args...) > // OK ???
struct Bar< void(*)(Args...), f >
{};

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

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

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

1 Ответ

0 голосов
/ 05 сентября 2018

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

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

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

template <typename T, typename U>
struct tuple_concat;

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

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

<ч />

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

...