[英]Require certain specialization of template as a template parameter
我有一个数据结构meta_array
,它使用变体作为类型 T 参数进行实例化。 要求是 std::variant 特化必须包含meta_array_head_t
类型,因为它用于跟踪信息。 我可以使用类型特征 (C++17) 以某种方式将此声明为要求吗?
#include <cstdio>
#include <variant>
#include <array>
struct meta_array_head_t {
// end_;
// remaining_;
// prev_;
};
template <typename T, size_t S> // make sure T = std::variant<... , meta_array_head_t, ...>
struct meta_array
{
std::array<T, S> data_;
};
using val = std::variant<std::monostate, int, double, meta_array_head_t>;
int main()
{
meta_array<val, 100> marray;
}
首先,确定T
是std::variant
类型,然后使用 fold 表达式检测替代类型是否包含meta_array_head_t
。
#include <variant>
template<typename T>
struct meta_variant : std::false_type { };
template<typename... Ts>
struct meta_variant<std::variant<Ts...>> :
std::bool_constant<((std::is_same_v<Ts, meta_array_head_t> || ...))> { };
template <typename T, size_t>
struct meta_array {
static_assert(meta_variant<T>::value,
"T must be a std::variant specialization "
"containing an alternative type of meta_array_head_t.");
};
使用std::disjunction_v
而不是 fold 表达式进行短路。
基于@康桓玮的回答。
template<typename T>
struct meta_variant : std::false_type { };
template<typename... Ts>
struct meta_variant<std::variant<Ts...>> {
static constexpr bool value = std::disjunction_v<std::is_same<Ts, meta_array_head_t>...>;
};
您可以使用专业化来编写特征。 您可以在不存在时将类型添加到变体中,而不是允许用户犯错误并且只产生错误:
#include <iostream>
#include <type_traits>
#include <variant>
struct foo {};
template <typename T>
struct has_foo_as_variant : std::false_type {};
template <typename... Ts>
struct has_foo_as_variant<std::variant<Ts...>> {
static constexpr bool value = (std::is_same_v<Ts,foo> || ...);
};
template <typename T>
constexpr bool has_foo_as_variant_v = has_foo_as_variant<T>::value;
template <typename T>
struct variant_with_foo;
template <typename...Ts>
struct variant_with_foo< std::variant<Ts...>> {
using type = std::conditional_t< has_foo_as_variant_v<std::variant<Ts...>>,
std::variant<Ts...>,
std::variant<foo,Ts...>>;
};
int main() {
using good_t = std::variant<foo,int,double>;
using bad_t = std::variant<int,double>;
std::cout << has_foo_as_variant_v<good_t>;
std::cout << has_foo_as_variant_v<bad_t>;
using foo_added_t = typename variant_with_foo<bad_t>::type;
std::cout << has_foo_as_variant_v<foo_added_t>;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.