繁体   English   中英

需要模板的某些特化作为模板参数

[英]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;
}

首先,确定Tstd::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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM