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

  • 本文关键字:参数 包中 变参 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> {};

最新更新