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

C++ std::variant - Type traits to verify that the contained variant types meet some assumptions

假设我有一些类型都有一个共同的父类:

struct some_tag;

struct A : some_tag;
struct B : some_tag;
struct C : some_tag;
struct D : some_tag;

单独地,可以使用以下方法测试一种类型是否是 some_tag 的子类型:

template <typename T>
using has_some_tag = std::is_base_of<some_tag, T>;

但是,假设我有一些变体可以接受任何数字和这些类型的任何组合,例如:

using variant_1 = std::variant<A,B,C>;
using variant_2 = std::variant<B,C>;
using variant_3 = std::variant<D,A>;
...

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

template <typename V>
struct some_other_type;

对于类型 V,我希望 static_assertions 符合以下条件:

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

我想我把所有的小部分都放在一起了,但我想不出检查变体类型的最佳方法。

我认为我需要的是一种特征,它可以有效地断言特定特征适用于每种基础类型。我应该指出,这里可以做的唯一假设是 V 应该只包含从 some_tag 继承的东西,但我们不能假设这需要的东西的顺序或数量。

有什么指点吗?

您可以使用偏特化:

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

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

然后写:

template<typename V>
struct some_other_type {
    static_assert(checker<V>::value);
};

或者,您可以使用 std::conjunction 而不是 && 折叠:

template<class... Ts> 
struct checker<std::variant<Ts...>> : std::conjunction<has_some_tag<Ts>...> {};

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