идиома обнаружения и совпадение типов параметров по умолчанию

Я могу написать следующее, чтобы определить, сериализуем ли объект.

template <typename T, typename = int>
struct is_serializable : std::false_type {};

template<typename T>
struct is_serializable <T, decltype(std::declval<std::ostream>() << std::declval<T>(), 0)> : std::true_type { };

template <typename T>
constexpr bool is_serializable_v = is_serializable<T>::value;

Я понимаю, что это выражение SFINAE, и перегрузка выбирается только в том случае, если тип выражения является выводимым. В противном случае выбрана реализация по умолчанию. Но почему результирующий тип decltype выражение соответствует типу параметра по умолчанию. Если я напишу следующий код, он больше не работает:

template <typename T, typename = int>
struct is_serializable : std::false_type {};

template<typename T>
struct is_serializable <T, decltype(std::declval<std::ostream>() << std::declval<T>(), 0L)> : std::true_type { };

template <typename T>
constexpr bool is_serializable_v = is_serializable<T>::value;

0

Решение

Во втором случае вы «специализируетесь»

struct is_serializable <T, long> // For T serializable

но вы просите в is_serializable_v тип is_serializable <T, int> который никогда не будет соответствовать вашей специализации.

Некоторое объяснение параметров по умолчанию:

template <typename T, typename = int>
struct is_serializable : std::false_type {};

// Specializations...

можно рассматривать как

template <typename T, typename = int>
struct is_serializable;
// So writing is_serializable<T> would be is_serializable<T, int>

template <typename T, typename>
struct is_serializable : std::false_type {};
// fallback for any combination not in specialization
// as <NonSerializable, int> <NonSerializable, std::string>
// <Serializable, string>
// but not <Serializable, int> which is part of specializations

// Specializations...
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]