C++20实现函数任意参数顺序调用并正确转发至目标函数
C++20 非暴力实现任意顺序参数调用指定顺序的bar函数
#include <concepts> struct T1 {}; struct T2 {}; struct T3 {}; struct T4 {}; void bar(T1, T2, T3, T4) { } template<typename T> concept IsT = std::same_as<T, T1> || std::same_as<T, T2> || std::same_as<T, T3> || std::same_as<T, T4>; void foo(IsT auto x1, IsT auto x2, IsT auto x3, IsT auto x4) { // 如何对x1、x2、x3、x4的类型排序并调用bar(x?, x?, x?, x?)? } int main() { foo(T1{},T2{},T3{},T4{}); // ok foo(T4{},T3{},T2{},T1{}); // ok foo(T3{},T2{},T1{},T4{}); // ok // ... }
需求说明
用户可以以任意参数顺序调用
foo函数,但最终要按正确顺序调用bar函数。
常规暴力解法是枚举24种参数排列,繁琐且易出错,以下是C++20下的非暴力解决方案:
解决方案
利用C++标准库的tuple和std::get<T>特性即可实现,无需枚举排列。std::get<T>可以从元组中直接提取指定类型的元素,只要该类型在元组中恰好出现一次(当前场景完全符合:foo的参数是T1-T4的一个排列,每个类型各出现一次)。
修改后的完整代码如下:
#include <concepts> #include <tuple> // 需包含tuple头文件 struct T1 {}; struct T2 {}; struct T3 {}; struct T4 {}; void bar(T1, T2, T3, T4) { } template<typename T> concept IsT = std::same_as<T, T1> || std::same_as<T, T2> || std::same_as<T, T3> || std::same_as<T, T4>; void foo(IsT auto x1, IsT auto x2, IsT auto x3, IsT auto x4) { auto args = std::make_tuple(std::move(x1), std::move(x2), std::move(x3), std::move(x4)); bar( std::get<T1>(args), std::get<T2>(args), std::get<T3>(args), std::get<T4>(args) ); } int main() { foo(T1{},T2{},T3{},T4{}); // ok foo(T4{},T3{},T2{},T1{}); // ok foo(T3{},T2{},T1{},T4{}); // ok // ... }
原理说明
std::make_tuple将foo的四个参数打包成元组,元组内包含T1-T4各一个实例(顺序任意)。std::get<T>(tuple)在编译期定位元组中类型为T的元素,直接提取后按bar要求的顺序传递。- 整个过程由编译期处理,无运行时开销,代码简洁易维护,无需处理任何排列逻辑。
内容的提问来源于stack exchange,提问作者xmllmx
相关产品推荐
相关产品推荐

