Когда я рассматриваю две следующие перегрузки:
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-значение, ссылка, cv-квалификаторы, указатель …), как в предыдущем случае? (и если да, то какой приоритет?)
Между этими двумя функциями нет универсального приоритета. Они одинаково конкурируют в алгоритме разрешения перегрузки. В общем, победит так называемая «универсальная ссылка», если только 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
}
Хороший совет никогда перегрузка вот так.
Других решений пока нет …