C++ 获取可变参数模板参数包中参数的并集?

标签 c++ templates

我一直在用 C++ 编写一些涉及大量元编程的代码;该代码对一个任务进行建模,该任务在运行时由一系列节点定义,这些节点接受多个输入,并在运行时产生一定数量的输出。输入和输出在有向图中链接。我将节点类型存储在变体中,并且每个节点类定义一个静态 constexpr 变量,该变量或多或少列出了该节点的输入和输出类型。我希望能够获取节点类别的列表,并将其转换为节点所作用的数据类别的列表。

更明确地说,如果我有一个在编译时纯粹跟踪某些类列表的模板,如下所示:

template<class... Args>
struct ClassList{};

我想要某种可以转换列表列表的模板,如下所示:

ClassList<ClassList<int,int,double>, ClassList<double,char>, ClassList<char, char> >

进入内部列表的并集:

ClassList<int,double,char>

对顺序没有特殊要求 - 除了原始列表中出现的每种类型在最终列表中只出现一次 - 如果可能的话,我希望以不会导致编译器爆炸的方式执行此操作。我知道理论上我可以编写一大堆递归模板,将列表连接成一个,然后删除重复项,但该解决方案听起来有点令人讨厌。有更好的办法吗?

最佳答案

在将类型添加到最终列表之前过滤类型的解决方案:

template<class... Ts>
struct class_list {};

template<class... Ts>
struct make_unique {
    using type = class_list<Ts...>;
};

template<class... Ts>
struct make_unique<class_list<>, Ts...> : make_unique<Ts...>{};

template<class U, class... Us, class... Ts>
struct make_unique<class_list<U, Us...>, Ts...> 
    : std::conditional_t<
          (std::is_same_v<U, Us> || ...) || (std::is_same_v<U, Ts> || ...), 
          make_unique<class_list<Us...>, Ts...   >,
          make_unique<class_list<Us...>, Ts..., U>> {};

template<class... Ts>
using make_unique_class_list = typename make_unique<Ts...>::type;

using T = make_unique_class_list<class_list<int, int, double>,
              class_list<double, char>, class_list<char, char>>;
static_assert(std::is_same_v<T, class_list<int, double, char>>);

请注意,以下看起来类似的解决方案也可以工作,但可能太慢,因为它实例化了许多不必要的模板:

template<class U, class... Us, class... Ts>
struct make_unique<class_list<U, Us...>, Ts...> 
    : std::conditional<
          (std::is_same_v<U, Us> || ...) || (std::is_same_v<U, Ts> || ...), 
          typename make_unique<class_list<Us...>, Ts...   >::type,
          typename make_unique<class_list<Us...>, Ts..., U>::type> {};

关于C++ 获取可变参数模板参数包中参数的并集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59403783/

相关文章:

c++ - C++ 中是否存在内存泄漏 "undefined behavior"类问题?

c++ - 为 Char 赋值重载 operator[] - C++

c++ - 矩阵模板,内存泄漏

c++ - 模板类中模板函数的重载

c++ - 当试图通过使用带有虚拟参数的模板别名来隐藏基类来混淆它们时,clang 和 gcc 之间的行为差​​异

c++ - 迭代器的大小与其容器的大小正相关吗?

c++ - 顶点着色器中的统一采样器2D

c++ - 在另一个函数中调用随机函数

c++ - 可以获得对象的静态类型吗?

C++ 模板 - 指定容器类型及其包含的容器元素类型