参数包排序(或等效行为)

Log*_*ick 1 c++ templates variadic-templates c++20

我想:

\n
template<class ... T>\nauto foo()\n{\n  // \xe2\x9c\xa8 magic \xe2\x9c\xa8\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这样:

\n
(foo<int, char, bool>() == foo<char, int, bool>()) // True\n(foo<int>() == foo<char>()) // False\n
Run Code Online (Sandbox Code Playgroud)\n

换句话说,我希望 foo 为传递给它的类型组合返回一个唯一的 id ,而不是传递给它的类型的排列。

\n

我的第一个想法是,可能有某种方法可以在编译时对参数包进行排序,尽管我不确定这到底是如何工作的。

\n

我目前的解决方案是这样的:

\n
// Precondition: Client must pass the parameters in alphabetical order to ensure the same result each time\ntemplate<class ... T>\nstd::type_index foo()\n{\n  return std::make_type_index(typeid(std::tuple<T ... >));\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这样做的问题是,如果客户端使用类型别名,它就不起作用。例如:

\n
using my_type = char;\n(foo<bool, int, my_type>() == foo<bool, char, int>()) // False\n
Run Code Online (Sandbox Code Playgroud)\n

我的一个想法是为函数处理的每个新类型分配一个新的素数作为 id。然后我可以通过将质数 id 相乘来为特定的类型组合分配一个唯一的 id。例如:

\n
id of int = 2\nid of bool = 3\nid of char = 5\nid of <int, bool, char> = 2 * 3 * 5 = 30\nid of <bool, int, char> = 3 * 2 * 5 = 30\n
Run Code Online (Sandbox Code Playgroud)\n

唯一的问题是我如何为每种类型分配唯一的质数 ID,而不会产生运行时损失。

\n

yur*_*hek 5

使用 Boost.Hana:

#include <boost/hana/set.hpp>
#include <boost/hana/type.hpp>

template<typename... T>
constexpr auto foo() {
    return boost::hana::make_set(boost::hana::type_c<T>...);
}

using my_type = char;
static_assert(foo<bool, int, my_type>() == foo<bool, char, int>());
Run Code Online (Sandbox Code Playgroud)