使用std::async调用含shared_ptr的模板类成员函数遇编译错误求助
我来帮你拆解一下问题出在哪,以及怎么修复:
首先看你出错的那段代码里的几个关键问题:
1. shared_ptr创建时的语法错误
你写的auto foo2 = std::make_shared<Foo<std::shared_ptr<Bar>>>;少了调用括号,正确的写法应该是auto foo2 = std::make_shared<Foo<std::shared_ptr<Bar>>>();——不过即使你补上括号,这里还有第二个更核心的问题。
2. 传递给std::async的对象指针类型不匹配
foo2是std::shared_ptr<Foo<std::shared_ptr<Bar>>>类型,如果你传&foo2,相当于把一个std::shared_ptr<...>*(指向智能指针的指针)传给了成员函数,但成员函数set_data需要的是Foo<std::shared_ptr<Bar>>*类型的this指针,类型不匹配直接导致模板参数推导失败。
3. 变量名笔误
你定义了auto br = std::make_shared<Bar>;,但后面调用时用的是bar,这也是编译报错的一个小诱因。
修复后的完整代码
你后来给出的修复版本是完全正确的,这里再明确一下逻辑:
#include "./foo.h" #include <memory> int main (int argc, char **argv) { // 直接在栈上创建Foo对象,避免智能指针的额外层级,简化指针传递逻辑 Foo<std::shared_ptr<Bar>> foo2; // 正确创建Bar的shared_ptr并初始化数据 auto bar = std::make_shared<Bar>(); bar->data = 2.5; // 传递foo2的地址作为this指针,参数bar的类型正好匹配set_data的参数要求 auto fut2 = std::async(std::launch::async, &Foo<std::shared_ptr<Bar>>::set_data, &foo2, bar); fut2.wait(); // get()返回shared_ptr<Bar>,直接访问其data成员即可 std::cout << fut2.get()->data << std::endl; return 0; }
如果你一定要用shared_ptr管理Foo对象
如果你的场景里必须用std::shared_ptr<Foo<std::shared_ptr<Bar>>>来持有Foo实例,调用std::async时有两种简洁的写法:
auto foo2 = std::make_shared<Foo<std::shared_ptr<Bar>>>(); auto bar = std::make_shared<Bar>(); bar->data = 2.5; // 写法1:用get()获取Foo对象的原始指针传递给async auto fut2 = std::async(std::launch::async, &Foo<std::shared_ptr<Bar>>::set_data, foo2.get(), bar); // 写法2:直接传递shared_ptr,std::async会自动处理this指针绑定 auto fut2 = std::async(std::launch::async, &Foo<std::shared_ptr<Bar>>::set_data, foo2, bar);
总结一下,问题的核心是传递给std::async的对象指针类型和成员函数期望的this指针类型不匹配,加上一些语法笔误,最终导致模板参数推导失败。当模板的参数是shared_ptr时,并没有特殊的语法要求,只是要注意智能指针本身的层级,不要把指向智能指针的指针错误传递进去。
内容的提问来源于stack exchange,提问作者amstrudy

