template<class...>struct types{typedef types type;};
template<class T, class types>struct contains:std::false_type {};
template<class T, class T0, class... Ts>struct contains<T, types<T0, Ts...>>:
std::integral_constant<bool,
std::is_same<T, T0>::value || contains<T, types<Ts...>>::value
>
{};
, SFINAE . std::is_convertible is_same.
typedef types<int,double, std::string> allowed_types;
template<typename T, typename=typename std::enable_if< contains<T, allowed_types>::value >::type>
T myFunc(T data) {
}
:
namespace details {
template<typename T>
T myFunc(T data, std::true_type) {
}
}
template<typename T>
T myFunc(T data) {
return details::myFunc(std::forward<T>(data), contains<T, allowed_types>{});
}
static_assert:
template<typename T>
T myFunc(T data) {
static_assert(contains<T, allowed_types>{}, "type not allowed");
}
all of which have various benefits. Although SFINAE seems tempting, I would advise him: it is fragile and can generate crazy error messages.
source
share