如何组合多可变模板/拆分参数包实现std::function通用乘法运算符
实现方案
核心实现
你需要的通用运算符可以直接通过双可变参数模板实现,不需要额外拆分参数包的工具,编译器可以独立推导两个操作数对应的参数包,不存在你担心的可变参数终止位置识别问题,完整实现如下:
#include <functional> #include <cstdint> #include <utility> using u64 = std::uint64_t; // 定义通用的op_type类型 template <typename... Args> using op_type = std::function<u64(u64, Args...)>; // 通用乘法运算符实现 template <typename... Ty1, typename... Ty2> op_type<Ty1..., Ty2...> operator*(const op_type<Ty1...>& f, const op_type<Ty2...>& g) { return [f, g](u64 num, Ty1... args_f, Ty2... args_g) -> u64 { // 先调用g,传入num和g对应的参数 u64 tmp = g(num, std::forward<Ty2>(args_g)...); // 再调用f,传入g的返回值和f对应的参数 return f(tmp, std::forward<Ty1>(args_f)...); }; }
说明
两个可变参数包Ty1和Ty2分别从两个输入参数f和g的类型独立推导,不会出现歧义:
Ty1对应f除首个u64参数外的所有参数类型Ty2对应g除首个u64参数外的所有参数类型- 返回的函数参数顺序为
u64+Ty1参数序列 +Ty2参数序列,完全符合你的需求
测试示例
对应你给出的用例,使用方式如下:
#include <iostream> int main() { op_type<int, int> f = [](u64 num, int i, int j) -> u64 { return num + ((i - j) ^ i); }; op_type<double> g = [](u64 num, double x) -> u64 { return num - static_cast<int>(num / x); }; auto h = f * g; // 测试调用:num=100, i=3, j=1, x=2.0 std::cout << h(100, 3, 1, 2.0) << std::endl; // 计算逻辑:g(100, 2.0) = 100 - 50 = 50; f(50, 3, 1) = 50 + (2^3) = 51,输出51 return 0; }
如果你希望直接传入普通函数、lambda等可调用对象无需手动包装成op_type,可以额外加一个辅助转换函数,C++17及以上版本可以直接用类模板参数推导实现:
template <typename Callable> auto to_op(Callable&& cb) { return op_type{std::forward<Callable>(cb)}; }
内容的提问来源于stack exchange,提问作者Qant123
相关产品推荐
相关产品推荐

