Насколько я понимаю ваш запрос, обнаружение недопустимого типа, вероятно, можно набросать как
template<class> struct ValidType;
template<template<class...> class> struct ValidContainer: std::false_type {};
template<> struct ValidContainer<std::vector>: std::true_type {};
template<class> struct ValidType: std::false_type {};
template<class> struct ValidType<double>: std::true_type {};
template<class> struct ValidType<std::string>: std::true_type {};
template<class> struct ValidArgument {
static_assert(false, "Both container and element type are wrong");
};
template<template<class...> class Ctr, class T, class... Ts>
struct ValidArgument<Ctr<T, Ts...>> {
static_assert(ValidContainer<Ctr>::value || ValidType<T>::value
, "Both container and element type are wrong");
static_assert(ValidContainer<Ctr>::value, "Container type is wrong");
static_assert(ValidType<T>::value, "Element type is wrong");
};
template<class T, std::size_t n> struct ValidArgument<std::array<T, n>> {
static_assert(ValidType<T>::value, "Element type is wrong");
};
(Обратите внимание, что это не реальный код, а просто демонстрация идеи.)
Массивы по-прежнему злые, в том смысле, что std::array
имеет параметр не-типа, и, таким образом, вы не можете иметь один шаблон, который проверяет контейнер, окончательная проверка по-прежнему для типа 0, с проверкой контейнера в общем случае.и std::array
рассматривается отдельно.
В качестве альтернативы ValidType
может быть несколько более компактным:
template<class T> using ValidType = std::bool_constant<
std::is_same_v<T, double> || std::is_same_v<T, std::string>>;
или
template<class T> using ValidType = std::disjunction<
std::is_same<T, double>, std::is_same<T, std::string>>;
или менее стандартным типомсоответствующий класс.Например:
template<class T, class... Ts> inline constexpr bool is_one_of_v =
std::disjunction_v<std::is_same<T, Ts>...>;
template<class T> using ValidType =
std::bool_constant<is_one_of_v<T, double, std::string>>;
Таким образом, у вас меньше шансов получить мошеннические специализации позже.