C++11环境下enqueue模板函数调用类成员函数编译错误的修复方案问询
解决C++11下enqueue模板调用成员函数的编译错误
我来帮你搞定这个问题,这本质上是C11和C14在类型推导规则上的差异导致的。先拆解错误原因,再给你适配C++11的修复方案。
错误原因分析
你原来的C++11版本模板里,返回类型用了decltype(f(args...)):
auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))>
当f是类成员函数指针(比如void (Test::*)(int))时,decltype(f(args...))在C11中无法正确解析——成员函数指针必须依附对象调用,但C11的decltype不会自动把第一个参数(对象指针/引用)和成员函数指针绑定,它会认为你在直接调用一个非成员函数,因此报出“called object type is not a function or function pointer”的错误。
而C++14版本改用std::result_of或者自动返回类型推导,能正确处理成员函数指针+对象参数的调用场景,所以编译正常。
C++11兼容的修复方案
我们可以借助C++11标准里的std::result_of来正确推导返回类型,替代原来的decltype(f(args...))写法。修复后的模板函数如下:
#include <future> #include <functional> template<class F, class... Args> auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F&&(Args&&...)>::type> { using return_type = typename std::result_of<F&&(Args&&...)>::type; auto task = std::make_shared<std::packaged_task<return_type()>>( std::bind(std::forward<F>(f), std::forward<Args>(args)...) ); auto future = task->get_future(); // 这里记得补充你原本的队列逻辑,把task加入线程队列执行 return future; }
为什么这个方案可行?
std::result_of<F&&(Args&&...)>::type会模拟完美转发后的调用行为:
- 对于普通函数指针,它直接推导函数返回值;
- 对于类成员函数指针,它会自动识别第一个参数是对象指针/引用,将成员函数指针与对象绑定后推导返回类型。
这样不管是调用普通函数还是类成员函数,类型推导都能正确完成,完美兼容C++11标准。
验证调用
你的原有调用代码可以直接正常使用:
Test test; cls->enqueue(&Test::display, &test, 0);
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

