Аргумент lvalue предпочитает ссылочный параметр lvalue универсальной ссылке?

Играя с универсальными ссылками, я наткнулся на случай, когда clang и gcc расходятся во мнениях относительно разрешения перегрузки.

#include <iostream>

struct foo {};

template<typename T>
void bar(T&) { std::cout << "void bar(T&)\n"; }

template<typename T>
void bar(T&&) { std::cout << "void bar(T&&)\n"; }

int main()
{
    foo f;
    bar(f);  // ambiguous on gcc, ok on clang
}

gcc сообщает, что приведенный выше вызов неоднозначен. Однако clang выбирает перегрузку T& и успешно компилируется.

Какой компилятор неправильный и почему?

Изменить:
Протестировал тот же код в предварительной версии VS2013, и он согласуется с clang; кроме Intellisense, который на стороне gcc :-)


person Praetorian    schedule 31.07.2013    source источник
comment
Это ошибка GCC 54425.   -  person Casey    schedule 31.07.2013
comment
Оба компилятора intel(13.0.1) и pgi(13.4) также выдают ошибку по этому поводу.   -  person Zulan    schedule 03.08.2013


Ответы (1)


«Универсальная ссылка» выводит параметр как foo&. Первый шаблон также выводит параметр в foo&.

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

person Johannes Schaub - litb    schedule 31.07.2013
comment
Нашел стандартную ссылку - из раздела N3691 §14.8.2.4/9. - person Praetorian; 31.07.2013