C ++ std :: variant-类型特征以验证所包含的变量类型是否满足某些假设

NOP*_*NOP 5 c++ templates type-traits variadic-templates c++17

假设我有一些具有共同父代的类型集:

struct some_tag;

struct A : some_tag;
struct B : some_tag;
struct C : some_tag;
struct D : some_tag;
Run Code Online (Sandbox Code Playgroud)

可以单独测试一个类型是否是以下项的子项some_tag

template <typename T>
using has_some_tag = std::is_base_of<some_tag, T>;
Run Code Online (Sandbox Code Playgroud)

但是,比方说,我有一些变体,可以接受任何数量和这些类型的任何组合,例如:

using variant_1 = std::variant<A,B,C>;
using variant_2 = std::variant<B,C>;
using variant_3 = std::variant<D,A>;
...
Run Code Online (Sandbox Code Playgroud)

然后,假设我正在使用这些变量类型作为模板参数传递给某个具有访问逻辑以处理每种类型的类。

template <typename V>
struct some_other_type;
Run Code Online (Sandbox Code Playgroud)

对于type V,我希望具有static_assertions,它满足以下条件:

  1. V 是一个变体
  2. V是一个变体,仅接受从继承的类型some_tag

我想我把所有的小片段都放在一起,但是我无法找到检查变体类型的最佳方法。

我认为我需要的是一个特征,可以有效地断言每种基础类型都具有特定的特征。我应该指出,这里V只能做的假设就是只包含继承自的东西some_tag,但我们不能对此所涉及的东西的顺序或数量做假设。

有指针吗?

Evg*_*Evg 5

您可以使用部分专业化:

template<class>
struct checker : std::false_type {};

template<class... Ts> 
struct checker<std::variant<Ts...>> : 
    std::bool_constant<(has_some_tag<Ts>::value && ...)> {};
Run Code Online (Sandbox Code Playgroud)

然后写:

template<typename V>
struct some_other_type {
    static_assert(checker<V>::value);
};
Run Code Online (Sandbox Code Playgroud)

或者,您可以雇用std::conjunction而不是&&弃用:

template<class... Ts> 
struct checker<std::variant<Ts...>> : std::conjunction<has_some_tag<Ts>...> {};
Run Code Online (Sandbox Code Playgroud)

编辑。 std::integral_constant<bool>被替换为std::bool_constant。谢谢,max66