如何在可变参数模板函数中传递(&类::成员函数, &类实例)形式参数
问题
已知std::thread和std::bind支持通过(&X::do_lengthy_work, &my_x)的形式传递成员函数参数,但自己实现的线程池submit可变参数模板函数,在调用pool.submit(&Test::print_one, &test)时触发错误,错误信息如下:
called object type 'remove_reference_t<void (Test::&)()>' (aka 'void (Test::)()') is not a function or function pointer
想问这种写法除了可变参数模板外,还需要做什么额外处理?之后根据建议把lambda表达式改成了使用std::invoke的版本:
auto func = [f, args...]() mutable { return std::invoke(std::forward<F>(f), std::forward<Args>(args)...); };
原因分析
直接调用成员函数指针是行不通的——成员函数指针本身不是可直接执行的函数/函数指针,它必须依附于类的实例(对象指针或引用)才能运行。之前线程池submit内部的lambda应该是直接写了f(args...),这种写法只能处理普通函数、函数指针或仿函数,没法正确解析成员函数指针+对象实例的组合,所以才会报类型错误。
解决方案
用std::invoke就是正确的处理方式:
std::invoke是C++17加入的标准库工具,能统一处理所有可调用对象,包括普通函数、函数指针、成员函数指针、仿函数、lambda表达式等。- 当传入的是成员函数指针时,
std::invoke会自动把后续第一个参数识别为类实例(指针或引用),并完成正确的绑定调用,完美适配(&Test::print_one, &test)这种传递方式。 - 搭配
std::forward实现完美转发,还能保证参数的引用类型和值类别正确传递,避免不必要的拷贝。
内容的提问来源于stack exchange,提问作者Qiuren
相关产品推荐
相关产品推荐

