如何调用接收std::function可变参数的C++ run模板函数?
关于std::function参数的run模板函数调用问题
你编写的第一个run模板函数可以通过编译,但调用时需要注意参数类型和值类别要求,先看原代码:
#include <iostream> #include <functional> #include <utility> #include <string> template<class... Args> void run(std::function<void(Args...)>&& f, Args&&... args) { f(std::forward<Args>(args)...); } void greet(std::string name, int times) { for(int i = 0; i < times; ++i) { std::cout << "Hello, " << name << "!\n"; } } int main() { std::function<void(std::string, int)> func = greet; run<std::string, int>(greet, std::string("Bob"), 2); // 无法运行 run(func, std::string("Bob"), 2); // 无法运行 return 0; }
原调用失败的原因
- 第一个调用
run<std::string, int>(greet, ...):greet是普通函数指针,不是std::function<void(std::string, int)>类型,无法匹配第一个参数的右值引用的std::function类型要求。 - 第二个调用
run(func, ...):func是左值对象,而第一个参数是std::function<void(Args...)>&&(这是确定类型的右值引用,不是模板参数的万能引用),左值不能直接绑定到非const的右值引用。
正确的调用方式
方式1:将左值std::function转为右值传入
利用std::move把已有的左值func转成右值,此时编译器可以自动推导模板参数:
run(std::move(func), std::string("Bob"), 2);
方式2:直接传入临时std::function对象(右值)
可以显式构造临时std::function作为参数,既可以显式指定模板参数,也可以让编译器推导:
// 显式指定模板参数 run<std::string, int>(std::function<void(std::string, int)>(greet), "Bob", 2); // 编译器自动推导Args run(std::function<void(std::string, int)>(greet), std::string("Bob"), 2);
对比通用版本的run函数
你提到的通用版本:
template<class Functor, typename... Args> void run(Functor&& f, Args&&... args) { f(std::forward<Args>(args)...); }
这里的Functor&&是万能引用(模板参数的右值引用),可以接受左值、右值、函数指针、lambda等各种可调用对象,类型推导更灵活,因此调用时不需要额外处理值类别或类型转换,适用性更广。
内容的提问来源于stack exchange,提问作者Qwe Qwe
相关产品推荐
相关产品推荐

