无法用Lambda作为自定义删除器构造std::unique_ptr的问题排查
问题原因与解决方案
错误原因
你遇到的C2641错误,本质是C++17的std::unique_ptr类模板推导规则不支持从lambda删除器自动推导模板参数。std::unique_ptr的第二个模板参数是删除器的类型,而lambda是匿名闭包类型,编译器无法通过构造函数的参数自动推导出这个匿名类型,因此无法完成模板参数推导。
解决方法
方法1:用decltype获取lambda类型(通用方案,支持带捕获的lambda)
先将lambda赋值给一个auto变量,再通过decltype获取其类型作为unique_ptr的第二个模板参数:
using FILE = int; FILE *f = nullptr; auto deleter = [](FILE *f) { /* 这里可以添加实际的释放逻辑,比如fclose(f) */ }; std::unique_ptr<FILE, decltype(deleter)> pf(f, deleter);
方法2:直接在模板参数中使用decltype(适用于无捕获lambda)
如果lambda没有捕获任何变量,可以直接在模板参数里用decltype推导:
using FILE = int; FILE *f = nullptr; std::unique_ptr<FILE, decltype([](FILE *f) {})> pf(f, [](FILE *f) {});
注:部分编译器可能需要C20及以上标准支持这种写法,C17下更推荐方法1。
方法3:指定函数指针作为删除器类型(仅适用于无捕获lambda)
无捕获的lambda可以隐式转换为对应的函数指针类型,因此可以直接将函数指针类型作为unique_ptr的第二个模板参数,无需decltype:
using FILE = int; FILE *f = nullptr; std::unique_ptr<FILE, void(*)(FILE*)> pf(f, [](FILE *f) {});
是否必须使用decltype?
不是必须的:
- 如果使用无捕获lambda,可以用函数指针类型代替,无需
decltype(如方法3); - 如果使用带捕获的lambda,由于带捕获的lambda无法转换为函数指针,只能使用其匿名闭包类型,这时候必须用
decltype来获取类型(如方法1)。
内容的提问来源于stack exchange,提问作者Alexey Starinsky
相关产品推荐
相关产品推荐

