Вы создали:
A<X>
, который использует параметр шаблона по умолчанию, чтобы стать:
A<X,void>
Однако ваша специализация:
template<typename T>
struct A<T, decltype(T().f())>
Что для параметра шаблона X
становится:
struct A<X, decltype(X().f())>
Что является:
struct A<X, bool>
Итак, ваша специализация не является правильным выбором, потому что A<X,bool>
не специализируется A<X,void>
.
Если вы хотите, чтобы ваша специализация работала для всех правильно сформированных экземпляров T().f()
, вы можете использовать C ++ 17's std::void_t
std::void_t
оценивается как void
для любых правильно сформированных параметров шаблона, переданных ему.
template<typename T>
struct A<T, std::void_t<decltype(T().f())>> {
void operator()() {
std::cout << "specialization" << std::endl;
}
};