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;