当显式默认析构函数时(例如:struct s { ~s() = default; };
),似乎该类型仍然可以在 constexpr
上下文中使用。但是,当显式删除析构函数时(例如:struct s { ~s() = delete; };
),Clang 不再认为该类型对于 constexpr
上下文是可行的。那么,正如标题所暗示的那样,具有显式删除析构函数的类型仍然可以在 constexpr
上下文中使用吗?
struct a { ~a() = default; }; // all ok
struct b { ~b(){} }; // all fail
struct c { ~c() = delete; }; // fails on clang
struct d { constexpr ~d() = default; }; // all ok
struct e { constexpr ~e(){} }; // all ok
struct f { constexpr ~f() = delete; }; // all ok
static_assert(noexcept([]<c>{}));
16.0.0和Clang trunk产生的错误:
<source>:9:28: error: non-type template parameter has non-literal type 'c'
static_assert(noexcept([]<c>{}));
^
<source>:3:12: note: 'c' is not literal because its destructor is not constexpr
struct c { ~c() = delete; }; // fails on clang
^
活生生的例子
对于一个文字类型的类,您只需要一个Constexpr
析构函数。=delete
d个函数长期以来一直被允许为Constexpr
。
但是,如果你不将其标记为constexpr,那么它不是constexpr
,除了具有额外规则的默认析构函数([class.dtor]p9):
默认析构函数是 constexpr 析构函数,如果它满足 constexpr 析构函数 ([dcl.constexpr]) 的要求。
一个没有成员的类会这样做,所以~a()=默认值
是常量表达式~c()=删除
不是constexpr,因为没有理由这样做。constexpr~f()=删除
是constexpr,因为它被标记为<code>constexpr</code>。
Clang在这里是正确的:~s() = delete;
如果未指定为,则不会是constexpr
,因此不能用作文字类型。似乎标准::is_literal_v
每个 cpp 首选项:
https://en.cppreference.com/w/cpp/language/constexpr
constexpr变量
Constexpr变量必须满足以下要求:
> <李> < p >...
(从C 20开始)它必须具有持续的破坏,即:
e
,如果对象的生存期及其不可变子对象(但不是其可变子对象)的生存期被认为是在 E 内开始的,则 E
将是一个核心常量表达式。
…
constexpr析构函数
(直到C 20)析构函数不能是constexpr,但可以在常量表达式中隐式调用普通析构函数。
(C 20起)函数体不是=delete;
必须满足以下附加要求: