Ошибка 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следует выбирать.

Это было исправлено в недавнем редактировании , которое я сделал.

Другие вопросы по тегам