显式删除的析构函数是否隐式标记为 constexpr?

303*_*303 31 c++ c++20

当显式默认析构函数时(例如:)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>{}));
Run Code Online (Sandbox Code Playgroud)

Clang 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
           ^
Run Code Online (Sandbox Code Playgroud)

实例

Art*_*yer 15

要使一个类成为文字类型,您所需要的只是一个constexpr析构函数。= deleted 功能已经被允许存在constexpr 很长时间了

但是,如果您不标记它constexpr,那么它除了constexpr具有额外规则([class.dtor]p9)的默认析构函数之外:

如果默认析构函数满足 constexpr 析构函数 ([dcl.constexpr]) 的要求,则它是 constexpr 析构函数。

没有成员的类会这样做,~a() = default;constexpr 也是如此。
~c() = delete;不是 constexpr 因为没有理由这样做。 constexpr ~f() = delete;是 constexpr 因为它被标记为constexpr.

Clang 在这里是正确的:如果未指定,则不会,因此不能用作文字类型~s() = delete;constexpr看来std::is_literal_v<c>gcc 错误地传递了。

  • 谈论“删除”函数的“constexpr”性质是不是很奇怪? (8认同)
  • @evg 我会说。甚至将析构函数标记为已删除也让我很头疼。 (3认同)