使用 C++ 模板元编程表示一组类型

Nar*_*yan 1 c++ template-meta-programming variadic-templates c++11 c++14

如何写一个模板 meta_set<class...Args>,使得 meta_set::type` 对于 Ts 的所有排列都是相同的?

换句话说,meta_set<>::type无论顺序如何,只要参数列表相同,我们就希望具有相同的值,也就是说,当将其视为一个集合(或多集合,如果更容易的话)。

例如,

std::is_same< meta_set<int,double,string>::type, meta_set<double,string,int>::type  >::value == true
std::is_same< meta_set<int,double,string>::type, meta_set<double,string,bool>::type  >::value == false
Run Code Online (Sandbox Code Playgroud)

当您希望每个模板参数有一个模板的单个实例化时,这可能会派上用场。

注意:这不是家庭作业,而是我在工作中处理模板繁重代码时感到好奇的事情。我不是元编程专家,所以我想也许人们可以分享他们的知识。

Yak*_*ont 5

没有办法在编译时对所有类型进行全局排序;获得类似的东西typeid(T).before(typeid(U))不是constexpr。因此,您不能将两个任意meta_set<A,B>meta_set<B,A>类型相同,因为您无法排序。

std::is_same如果类型不同,则无法修改返回 true的行为。任何试图这样做的代码(比如通过 specialize std::is_same)都会违反 的要求std::is_same,这将使程序格式错误,不需要诊断。

如果您将类型集限制为所有类型的某个子集,则可以执行此操作。最简单的方法是拥有一个集中列表:

template<class...T>
struct types_t {};

using global_order = types_t<int, double, std::string>;
Run Code Online (Sandbox Code Playgroud)

然后,通过一些模板元编程,您可以获得 中的类型索引global_order,然后基于此编写类型排序器。

然后

template<class Types>
struct type_sorter;

template<class...Ts>
struct type_sorter<types_t<Ts...>> {
  // todo
  using type=types_t< result_somehow >;
};
Run Code Online (Sandbox Code Playgroud)

一旦这样写:

template<class...Ts>
using meta_set = typename type_sorter< types_t<Ts...> >::type;
Run Code Online (Sandbox Code Playgroud)

会工作。

可能有关于如何在编译时使用堆栈溢出模板对内容进行排序的解决方案。我个人发现合并排序最容易在所有 n log(n) 排序的模板元编程中编写。上次它花了大约 100 多行密集的模板代码?包括编写一个 TMP 库。但是,现在存在 TMP 库,甚至可能已经为您预先编写了类型排序代码。

现在,单一的全局排序是最简单的事情。我们可以通过教类型排序器关于模板、对模板进行排序,然后通过它们的组成类型和值等对所述模板实例进行排序来使其更强大一些。

这变得很困难,它需要为每个模板工作,支持的模板类型(所以template<class...>classvs template<class, std::size_t>class)和基本类型(int, float, struct foo)。

这将是很多工作。

编写自定义特征稍微容易一些

template<class Lhs, class Rhs>
struct smart_is_same;
Run Code Online (Sandbox Code Playgroud)

这就像std::is_same,除非 fedmeta_set会检查它们是否具有相同的内容而不是寻找严格的类型相等性。但是,您的评论提到这不是您的实际问题,而是您正在谈论将meta_set参数传递给不同的模板并希望它们按规范顺序排列。