类专属释放函数能否用于常量表达式?哪种编译器行为正确?
类专属destroying delete能否用于常量表达式?
能否定义类专属释放函数并将其用于常量表达式中?比如以下使用destroying delete的示例代码:
#include <new> struct A { constexpr void operator delete(A *, std::destroying_delete_t); }; struct B : A {}; constexpr void A::operator delete(A *p, std::destroying_delete_t) { ::delete static_cast<B*>(p); } constexpr bool foo() { A *p = new B; delete p; return true; } static_assert( foo() );
这段代码在GCC和MSVC中可以正常编译通过,但Clang会报出如下错误:
error: constexpr function never produces a constant expression [-Winvalid-constexpr] note: call to class-specific 'operator delete'
哪种编译器的行为符合C++标准?
根据C++20及后续标准的规定:
- 允许将类专属的
operator delete声明为constexpr,只要其实现满足常量表达式的约束; - 在常量表达式中执行
delete操作时,只要被释放的内存是由常量表达式内的constexpr new分配,且对应的operator delete是constexpr的,同时操作本身无未定义行为,就属于合法的常量表达式。
回到示例代码:
foo()中的new B是在常量表达式上下文内分配内存,符合要求;- A的专属
operator delete被声明为constexpr,其内部调用的全局delete针对的是常量表达式中分配的B对象,操作本身无未定义行为。
因此GCC和MSVC的行为符合C++标准,Clang的报错属于对该特性的实现滞后或标准解读偏差。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

