Это ошибка.
template <class C> struct special<void(C::*)()>; // specialization 1
template <class R, class C> struct special<R(C::*)()>; // specialization 2
Согласно 14.5.4.2, частичное упорядочение этих двух специализаций шаблонов классов такое же, как частичное упорядочение этих шаблонов мнимых функций:
template <class C> void f(special<void(C::*)()>); // func-template 3
template <class R, class C> void f(special<R(C::*)()>); // func-template 4
Согласно 14.5.5.2, частичное упорядочение этих двух шаблонов функций определяется путем замены изобретенных типов для каждого параметра шаблона типа в списке аргументов одного и попытки вывода аргумента шаблона с использованием этого списка аргументов в другом шаблоне функции.
// Rewrite the function templates with different names -
// template argument deduction does not involve overload resolution.
template <class C> void f3(special<void(C::*)()>);
template <class R, class C> void f4(special<R(C::*)()>);
struct ty5 {}; struct ty6 {}; struct ty7 {};
typedef special<void(ty5::*)()> arg3;
typedef special<ty6 (ty7::*)()> arg4;
// compiler internally tests whether these are well-formed and
// the resulting parameter conversion sequences are "exact":
f3(arg4());
f4(arg3());
Подробности вывода аргументов шаблона приведены в 14.8.2.Среди действительных вычетов от template_name<dependent_type>
и dependent_type1 (dependent_type2::*)(arg_list)
.Таким образом, вывод f4(arg3())
успешен, вывод f4<void,ty5>(arg3());
.Вывод f3(arg4())
, очевидно, никогда не может быть успешным, поскольку void
и ty6
не объединяются.
Поэтому шаблон функции 3 более специализирован, чем шаблон функции 4. А специализация шаблона класса 1 более специализирована, чем классспециализация шаблона 2. Таким образом, хотя special<void(s::*)()>
соответствует обеим специализациям, оно однозначно определяет специализацию 1.