Универсальный опорный приоритет vs const?
Когда я рассмотрю две следующие перегрузки:
template <class... T> void f(const T&... x);
template <class T> void f(const T& x);
У меня есть гарантия, что f(x)
всегда будет вызывать вторую функцию и никогда не приведет к двусмысленности. В некотором смысле вторая версия является общепринятой по сравнению с первой для одного аргумента независимо от его типа.
Теперь рассмотрим ситуацию, когда существует универсальная ссылка и константные эталонные версии функции:
template <class T> void f(T&& x);
template <class T> void f(const T& x);
Мой вопрос: является ли их универсальным приоритетом между этими двумя функциями независимо от типа x (r-value reference, reference, cv-qualifiers, pointer...), как в предыдущем случае? (и если да, то какой приоритет?)
Ответы
Ответ 1
Между этими двумя функциями нет универсального приоритета. Они одинаково конкурируют в алгоритме разрешения перегрузки. В общем, так называемая "универсальная ссылка" выигрывает, если const T&
не является точным совпадением, и выигрывает const T&
.
struct A {};
int
main()
{
f(std::declval<A>()); // calls f<A>(A&&), #1
f(std::declval<const A>()); // calls f<const A>(const A&&), #1
f(std::declval<A&>()); // calls f<A&>(A&), #1
f(std::declval<A&&>()); // calls f<A>(A&&), #1
f(std::declval<const A&&>()); // calls f<const A>(const A&&), #1
f(std::declval<const A&>()); // calls f<A>(const A&), #2
}
Хороший совет - перегрузка никогда, как это.