C++23中用静态operator()作unique_ptr删除器是否合规?编译疑问解析
C++23中std::unique_ptr静态删除器代码的合法性解析
一、代码是否符合C++23标准?
这段代码是符合C++23标准的。
std::unique_ptr的第二个模板参数Deleter仅需满足可调用要求:该类型的实例能够接受int*类型参数并执行删除逻辑即可。这里我们用静态成员函数custom_deleter::operator()的指针作为Deleter类型,函数指针本身具备可调用性,同时构造unique_ptr时也传入了对应的函数指针实例,完全符合unique_ptr的构造规则,属于标准允许的写法。
二、移除&导致编译错误的原因
去掉decltype(&custom_deleter::operator())中的&后,decltype的参数变为custom_deleter::operator()——这是一个重载集的名字,而非明确的表达式。
C++语法中,decltype需要作用于确定的表达式或类型名。直接写custom_deleter::operator()时,编译器无法从这个重载集名字中锁定具体的函数(哪怕这里只有一个重载,语法上仍会被视为重载集),因此无法推导出有效类型,最终触发编译错误。而加上&后,&custom_deleter::operator()是获取静态成员函数指针的明确表达式,编译器能推导出对应的函数指针类型void(*)(int* const),此时decltype就能得到正确的类型。
三、Deleter模板参数必须是函数指针类型吗?
完全不需要。std::unique_ptr的Deleter可以是任何满足可调用要求的类型,常见替代类型包括:
- 带非静态
operator()的仿函数类:struct CustomDeleter { void operator()(int* ptr) { delete ptr; std::fputs("Deleted\n", stdout); } }; std::unique_ptr<int, CustomDeleter> ptr(new int{5}); - lambda表达式类型:
auto deleter = [](int* ptr) { delete ptr; std::fputs("Deleted\n", stdout); }; std::unique_ptr<int, decltype(deleter)> ptr(new int{5}, deleter); std::function包装类型:std::unique_ptr<int, std::function<void(int*)>> ptr( new int{5}, [](int* p) { delete p; std::fputs("Deleted\n", stdout); } );
只要某类型的实例能被调用并处理对应指针参数,就可以作为unique_ptr的Deleter。
内容的提问来源于stack exchange,提问作者digito_evo
相关产品推荐
相关产品推荐

