Ошибка MSVC vs Clang/GCC при разрешении перегрузки шаблонов функций, один из которых содержит пакет параметров
Я использовал пакет параметров, когда заметил, что один из таких случаев (показан ниже) отлично компилируется в gcc и clang, но не в msvc:
template<class T> void func(T a, T b= T{})
{
}
template<class T, class... S> void func(T a, S... b)
{
}
int main()
{
func(1); // Should this call succeed?
}
Вот ссылка для проверки: https://godbolt.org/z/8KsrcnMez
Как видно, приведенная выше программа завершается сбоем в msvc с сообщением об ошибке:
<source>(13): error C2668: 'func': ambiguous call to overloaded function
<source>(6): note: could be 'void func<int,>(T)'
with
[
T=int
]
<source>(2): note: or 'void func<int>(T,T)'
with
[
T=int
]
<source>(13): note: while trying to match the argument list '(int)'
Но то же самое отлично компилируется с gcc и clang.
Какой компилятор (ы) здесь?
1 ответ
MSVC прав, отвергая код. Согласно temp.func.order#5.example-2 вызов неоднозначен. Пример, приведенный в стандарте, выглядит следующим образом:
Примечание. Поскольку в контексте вызова такой вывод типа учитывает только параметры, для которых существуют явные аргументы вызова, некоторые параметры игнорируются (а именно, пакеты параметров функции, параметры с аргументами по умолчанию и параметры с многоточием).
template<class T > void g(T, T = T()); // #3 template<class T, class... U> void g(T, U ...); // #4 void h() { g(42); // error: ambiguous }
Это означает, что в рассматриваемом примере вызовfunc(1)
тоже неоднозначно.
Опечатки
Обратите внимание, что cppreference содержит опечатки в приведенном ниже примере:
template<class T> void g(T, T = T()); // #1 template<class T, class... U> void g(T, U...); // #2 void h() { g(42); // calls #1 due to the tie-breaker between parameter pack and omitted parameter }
Как видно из приведенного выше примера, cpprefernce неправильно говорит, что первая перегрузка#1
следует выбирать.
Это было исправлено в недавнем редактировании , которое я сделал.