如何传递模板函数作为参数并自动推导其类型?
无需指定类型或Lambda包装,直接传递全局模板函数的方法
global_op和local_op功能完全一致,但Lambda可以直接传给func且类型自动推导,全局模板函数却不行——指定模板参数虽然能运行,但我们没法提前知道func内部使用的类型;用Lambda包装又多了一层冗余。那有没有办法不用指定类型、也不用Lambda包装,直接把全局模板函数当参数传递?
原代码示例:
#include <iostream> auto func(auto&& operation) { return operation(1, 2); } auto global_op(auto&& x, auto&& y) { return x + y; } int main() { auto local_op = [](auto&& x, auto&& y) { return x + y; }; auto local_op_2 = [](auto&& x, auto&& y) { return global_op(x, y); }; std::cout << func(local_op) << std::endl; // 正常编译 //std::cout << func(global_op)<< std::endl; // 编译失败 std::cout << func(global_op<int, int>) << std::endl; // 可行,但必须手动指定类型 std::cout << func(local_op_2) << std::endl; // 可行,但需要Lambda包装 return 0; }
核心原因
全局模板函数的名字global_op不是一个具体的函数实例,而是一整组重载函数的标识。编译器无法自动判断要选择哪一个实例传递给func;而Lambda或仿函数是具体的对象,它们的operator()模板可以在调用时自动推导参数类型。
解决方案
1. 用仿函数替代全局模板函数
把全局模板函数改成带模板operator()的结构体,它的实例是具体对象,能直接传给func,调用时自动推导类型:
#include <iostream> auto func(auto&& operation) { return operation(1, 2); } struct global_op { template<typename T, typename U> auto operator()(T&& x, U&& y) const { return x + y; } }; int main() { std::cout << func(global_op{}) << std::endl; // 直接传实例,编译通过 return 0; }
2. C++20及以上:用std::bind_front生成可调用对象
如果不想修改原global_op,可以用std::bind_front生成包装对象,无需手动编写Lambda:
#include <iostream> #include <functional> auto func(auto&& operation) { return operation(1, 2); } auto global_op(auto&& x, auto&& y) { return x + y; } int main() { std::cout << func(std::bind_front(global_op)) << std::endl; // 编译通过 return 0; }
3. 给func添加模板参数重载(灵活性稍差)
修改func让它接受模板模板参数,不过需要把全局函数包装成模板化的函数对象:
#include <iostream> #include <utility> template<template<typename...> typename Op> auto func() { return Op<int, int>{}(1, 2); } template<typename T, typename U> auto global_op(T&& x, U&& y) { return x + y; } template<typename T, typename U> struct global_op_wrapper { auto operator()(T&& x, U&& y) const { return global_op(std::forward<T>(x), std::forward<U>(y)); } }; int main() { std::cout << func<global_op_wrapper>() << std::endl; return 0; }
内容的提问来源于stack exchange,提问作者user3324131
相关产品推荐
相关产品推荐

