[英]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.