Список переменных в сравнении с одним параметром шаблона: что говорит стандарт?

Рассмотрим следующий код:

#include <iostream>
#include <type_traits>

// Variadic version
template<class... Variadic>
void f(const Variadic&... variadic)
{
std::cout<<"variadic"<<std::endl;
}

// Single version
template<class Single, class = typename std::enable_if<std::is_fundamental<Single>::value>::type>
void f(const Single& single)
{
std::cout<<"single"<<std::endl;
}

// Main
int main()
{
f();              // variadic
f(42);            // single : why?
f(std::string()); // variadic
f(42, 42);        // variadic
return 0;
}

Я не понимаю, почему строка, помеченная как «одиночная», хорошо компилируется (в g ++ 4.6.3) и не создает проблемы с разрешением перегрузки. Говорит ли стандарт c ++ 11, что шаблонная функция с фиксированным числом параметров предпочтительнее, чем переменная функция, которая может иметь такую ​​же сигнатуру?

5

Решение

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

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

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

2

Другие решения

Это правда достаточно просто (два живых примера, gcc и clang)

template<class...T> void foo(T&&...) {std::cout << "...T\n";}
template<class T> void foo(T&&) {std::cout << "T\n";}
int main() {
foo(3);
}

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

class=std::enable_if_t не меняет это.

Так что обе ваши функции f являются кандидатами, то компилятор предпочитает тот, у которого нет вариаций.

/ 8:

Если A был преобразован из пакета параметров функции и P не является пакетом параметров, вывод типа завершается ошибкой. В противном случае, используя результирующие типы P а также Aзатем вычет производится, как описано в 14.8.2.5, Если P это пакет параметров функции, тип A каждого оставшегося типа параметра шаблона аргумента сравнивается с типом P идентификатора объявления
пакета параметров функции. Каждое сравнение выводит аргументы шаблона для последующих позиций в пакетах параметров шаблона, расширенных пакетом параметров функции. Если для данного типа вывод выполняется успешно, считается, что тип из шаблона аргумента является по меньшей мере таким же специализированным, как и тип из шаблона параметра. [
Пример:

template<class... Args> void f(Args... args); // #1
template<class T1, class... Args> void f(T1 a1, Args... args); // #2
template<class T1, class T2> void f(T1 a1, T2 a2); // #3
f(); // calls #1
f(1, 2, 3); // calls #2
f(1, 2); // calls #3; non-variadic template #3 is more
// specialized than the variadic templates #1 and #

В частности, f(1,2) пример.

Все enable_if_t предложение делает это удалить версию с одним аргументом из рассмотрения, когда вы передаете std::string как T,

5

По вопросам рекламы [email protected]