I can write the following to detect, if an object is serializable.
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;
I do understand that this is expression SFINAE and the overload is only selected if the type of the expression is deducible. Otherwise the default implementation is chosen. But why must the resulting type of the decltype
expression match the type of the default parameter. If I write the following code it does no longer work:
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;
In the second case, you "specialize"
but you request in
is_serializable_v
the typeis_serializable <T, int>
which will never match with your specialization.Some default parameter explanation:
can be seen as