簡體   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