В вне строки определения вы удаляете аргументы по умолчанию, они взяты из объявлений:
template <class T>
template <typename U, typename std::enable_if_t<!std::is_same<U, int>::value && !std::is_same<U, float>::value,int>>
void Foo<T>::sfinae() { // Foo<anything else>
std::cout << "sfinae default" << std::endl;
}
то же самое для остальных
регистр по умолчанию для всех ловушек (который печатает sfinae-default) в настоящее время должен быть записан как not(type1, type2,...)
, что потенциально может быть огромным.Возможно ли более короткое / более чистое решение?
Для этого вам нужно добавить дополнительный параметр для ранжирования перегрузок, дающий наименьший ранг универсальному, это обычно делается с использованием того факта, чтопараметр многоточия не лучше, чем любой другой тип параметра:
template <typename U = T>
void sfinae(...);
template <typename U = T, typename std::enable_if_t<std::is_same<U, int>::value,int> = 0>
void sfinae(int);
template <typename U = T, typename std::enable_if_t<std::is_same<U, float>::value,int> = 0>
void sfinae(int);
Foo<char>{}.sfinae(0); // select the catch-all
Это означает, что, поскольку ...
хуже, чем любой другой параметр (int
лучше, чем ...
), перегрузкаsfinae(...)
рассматривается только в том случае, если два других не могут быть вызваны, т. Е. Если они СФИНАЕ.