#include <iostream>
#include <utility>
template <class T> struct is_rvalue_ref : std::false_type {};
template <class T> struct is_rvalue_ref<T&&> : std::true_type {};
template <typename T> bool is_rvalue_ref_func(T){return false;}
template <typename T> bool is_rvalue_ref_func(T&&){return true;}
class A {};
int main()
{
std::cout << std::boolalpha;
std::cout << is_rvalue_ref<A>::value << '\n';
std::cout << is_rvalue_ref<A&>::value << '\n';
std::cout << is_rvalue_ref<A&&>::value << '\n';
/*****THIS FAILS TO COMPILE************
A a;
A& alv = a;
A&& arv = std::move(a);
std::cout << is_rvalue_ref_func(a) << '\n';
std::cout << is_rvalue_ref_func(alv) << '\n';
std::cout << is_rvalue_ref_func(arv) << '\n';
**************************************/
return 0;
}
Компилятор (clang 3.5 -std=c++11
) не имеют никаких проблем неоднозначности вызовы is_rvalue_ref
пока он уклоняется от is_rvalue_ref_func
перегрузок с:Почему следующий шаблон шаблона не является двусмысленным?
rv.cpp:31:16: error: call to 'is_rvalue_ref_func' is ambiguous
std::cout << is_rvalue_ref_func(a) << '\n';
^~~~~~~~~~~~~~~~~~
rv.cpp:8:6: note: candidate function [with T = A]
bool is_rvalue_ref_func(T)
^
rv.cpp:14:6: note: candidate function [with T = A &]
bool is_rvalue_ref_func(T&&)
^
rv.cpp:32:16: error: call to 'is_rvalue_ref_func' is ambiguous
std::cout << is_rvalue_ref_func(alv) << '\n';
^~~~~~~~~~~~~~~~~~
rv.cpp:8:6: note: candidate function [with T = A]
bool is_rvalue_ref_func(T)
^
rv.cpp:14:6: note: candidate function [with T = A &]
bool is_rvalue_ref_func(T&&)
^
rv.cpp:33:16: error: call to 'is_rvalue_ref_func' is ambiguous
std::cout << is_rvalue_ref_func(arv) << '\n';
^~~~~~~~~~~~~~~~~~
rv.cpp:8:6: note: candidate function [with T = A]
bool is_rvalue_ref_func(T)
^
rv.cpp:14:6: note: candidate function [with T = A &]
bool is_rvalue_ref_func(T&&)
^
3 errors generated.
Однако, по словам 14.5.5.2 [temp.class.order]
Для два шаблона класса частичных специализация, первая по меньшей мере равна как специализированная, как вторая, если с учетом следующей перезаписи на две функции: function templ Атес, первый шаблон функции, по крайней мере специализирован как вторые в соответствии с правилами заказа для функции шаблонов (14.5.6.2):
- первый шаблон функции имеет те же параметров шаблона в качестве первой частичной специализации и имеет параметр в одной функции, тип которого шаблон класса специализации с аргументами шаблона первой частичной специализации и
- второй шаблон функции имеет те же параметров шаблона как вторая частичную специализация и имеет параметр одиночной функции, тип которого является шаблоном класса специализация с аргументами шаблона второй частичной специализации .
В приведенном выше примере, is_rvalue_ref_func
Перегрузки получаются путем выполнения именно это переписывание is_rvalue_ref
первичного шаблона и частичной специализации. Почему вызов функции неоднозначен, но шаблон шаблона соответствует четко определенному?
Шаблоны функций не являются частично специализированными. Вместо этого они перегружены, и есть две одинаково хорошие перегрузки. Обратите внимание: вы не можете частично специализировать шаблон функции, вы можете полностью их специализировать. –
@ DietmarKühl Согласен. Исправлено неточное название. Шаблоны функций, показанные в примере, являются просто перегрузками. Однако они генерируются в соответствии с правилами сопоставления шаблонов классов, указанными в вопросе. – Pradhan
текст, который вы цитировали, говорит о «специализациях классов». Это 1. полная специализация с использованием аргументов, предоставляемых шаблону класса, 2. они являются классами. Вы кодируете для шаблонов функций ни один из них. –