15

При разрешении неоднозначностей между перегрузками шаблонов функций выполняется частичное упорядочение (см. here для некоторых пояснений). В этом веб-сайте, мы также узнаем, чтоЧто такое «пассивный пакет параметров»

В случае равенства, если один шаблон функции имеет параметр Продольный пакет, а другой не делает, тот с опущенным параметром является считается более специализированным, чем один с пустым пакетом параметров .

Теперь, интересно, что именно trailing параметр pack есть. Что если какой-либо из

template<class ...> struct tuple { /* ... */ }; 

template<class T, class...Ts> void foo(tuple<T,Ts...>); 

template<class T, class...Ts> void bar(T, Ts...); 

есть, а какие нет и почему? Следует также отметить, что лязг считает

template<class T> void f(tuple<T>); 

template<class T, class...Ts> void f(tuple<T,Ts...>); 

int main() 
{ f(tuple<int>()); } // ambiguous call? 

неоднозначным, подразумевая, что foo не имеет косые параметры пакета.

+1

Lol, эти два комментария противоречат друг другу! Поэтому есть что обсудить. – Walter

+0

@ Jarod42 Итак, вы говорите, что «trailing parameter pack» относится к аргументам функции, а не параметрам шаблона? – Walter

+0

Действительно, clang и gcc не согласны [Demo] (http://coliru.stacked-crooked.com/a/6f67a0a696424a56). – Jarod42

ответ

7

Это CWG1395, для которого дефект resolution был недавно проголосован за проект стандарта C++ 17. Далее был добавлен в [temp.deduct.partial]:

... [если] шаблон функции F, по меньшей мере, специализировался в качестве матрицы G функции, и наоборот, и если G имеет параметр трейлинг пакет для которых F не имеет соответствующего параметра, и если F не имеет завершающего пакета параметров, то F более специализирован, чем G.

Стандарт не явно определить, что это означает, что с помощью «трейлинг параметров пакета», но, судя по существующим контексты, в которых используется этот термин, он относится к параметру шаблона пакета, который появляется в качестве крайнего правого параметра список параметров шаблона:

template<class T, class... U> struct X; 
//    ^^^^^^^^^^ 

Или параметр функции пакета, который появляется в качестве крайнего правого параметра в списке параметров:

template<class T, class... U> void y(T, U...); 
//          ^^^^ 

текущий проект все еще содержит это устаревший пример в [temp.deduct.type]:

template<class T, class... U> void f(T, U...); 
template<class T> void f(T); 

f(&i); // error: ambiguous 

Этого стандартном отчете дефект был вокруг в течение нескольких лет, и оба GCC и Clang внедрили решения этого. Они оба согласны с тем, что приведенный выше пример является действительным вызовом второй перегрузки f.

Где GCC и Clang не согласны с объемом разрешения дефекта. Это понятно, поскольку он был недавно обновлен, чтобы включить предлагаемую стандартную формулировку. В вашем примере, пакет не разлагаются в списке параметров функции, но в список аргументов шаблона из типа параметра функции:

template<class T, class... U> void g(tuple<T, U...>); 
template<class T> void g(tuple<T>); 

g(tuple<int>{}); 

ССАГПЗ рассматривает это как действительный вызов второй перегрузки g; Кланг рассматривает это как неоднозначное.Правильность Clang может зависеть от того, должен ли «trailing parameter pack» включать в себя завершающий набор шаблонов или только завершающий набор параметров .

Обратите внимание, что оба составителей согласны, что C<int> относится ко второй частичной специализации шаблона класса C в следующем примере:

template<class...> struct C; 

template<class T, class... U> struct C<T, U...> {}; 
template<class T> struct C<T> {}; 

Это кажется несогласованность в Clang, так как стандартные правила для частичного упорядочения специализация шаблонов классов определяется в части частичного упорядочения шаблонов функций. См. CWG1432.

+2

Резолюция для CWG1395 только что была проголосована в последнем рабочем проекте, см. [N4619] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4619.html). Полагаю, откуда взялся текст cppreference. К сожалению, это не похоже на 1432, и это не единственная проблема, которую я вижу там. Для получения дополнительной информации ознакомьтесь с [это обсуждение] (https://chat.stackoverflow.com/rooms/130228/discussion-between-bogdan-and-barry). – bogdan

+0

Просто выполнил быстрый тест, и MSVC согласен с GCC: [версия 'template ' превосходит версию 'template ' в обоих случаях] (http://rextester.com/FEKSB40747). Я, честно говоря, удивлен, что они решили версию 'g()' быстрее, чем Clang. –

+0

Есть ли пакеты параметров, которые не заканчиваются? –

0

Trailing означает «в конце».

Трейлинг параметр пакета является параметром пакет находится в конце списка параметров шаблона:

template <typename T1, typename... Ts> 
void foo(); 

//^Ts... is trailing here 

Это не C++ вопрос, но английский вопрос.

+4

Да ... может быть, в более простой вселенной, одна полная ... легкости, где пачки - бесцветные существа, радостно ... гоняющие друг друга, пытаясь выяснить, кто за ним. Конечно, если они все ... на орбите вокруг стандартной черной дыры, то никто не может по-настоящему отстать. Теперь я еще более смущен. – bogdan

+1

в вашем коде нет 'Ts ...'. – Walter

+0

@Walter: 'template ' –

Смежные вопросы