为什么不能将析构函数标记为constexpr?

问题描述 投票:29回答:5

在C ++中,你可以将许多东西声明为constexpr:变量,函数(包括成员函数和运算符),构造函数,以及自C ++ 1z以及if statementslambda expressions。但是,声明destructor constexpr会导致错误:

struct X {
    constexpr ~X() = default; // error: a destructor cannot be 'constexpr'
};

我的问题:

  1. 为什么不能将析构函数标记为constexpr
  2. 如果我不提供析构函数,是隐式生成的析构函数constexpr吗?
  3. 如果我声明一个默认的析构函数(~X() = default;),它会自动constexpr吗?
c++ language-lawyer constexpr
5个回答
11
投票

根据draft basic.types#10可能具有cv限定的类类型,它具有以下所有属性:

可能具有cv限定的类类型,具有以下所有属性:

(10.5.1) - 它有一个简单的析构函数,

(10.5.2) - 它是一个闭包类型,一个聚合类型,或者至少有一个constexpr构造函数或构造函数模板(可能从一个基类继承),它不是一个复制或移动构造函数,

(10.5.3) - 如果它是一个联合,它的至少一个非静态数据成员是非易失性文字类型

(10.5.4) - 如果它不是联合,则其所有非静态数据成员和基类都是非易失性文字类型。

问题1:为什么析构函数不能被标记为constexpr?

因为只有琐碎的析构函数才有资格获得constexpr以下是draft的相关部分

如果不是用户提供的析构函数是微不足道的,如果:

(5.4) - 析构函数不是虚拟的,

(5.5) - 同类的所有直接基类都有琐碎的析构函数

(5.6) - 对于类的所有类型(或其数组)的非静态数据成员,每个这样的类都有一个简单的析构函数。

否则,析构函数是非平凡的。

问题2:如果我不提供析构函数,是隐式生成的析构函数constexpr吗?

是的,因为隐式生成的析构函数是微不足道的类型,因此它符合constexpr的条件

问题3:如果我声明一个默认的析构函数(~X()= default;),它会自动constexpr吗?

实际上,这个析构函数是用户声明的并且是隐式生成的,因此它符合constexpr的条件。


我无法找到任何直接的参考,只有微不足道的destructors符合constexpr,但如果析构函数不是微不足道,那么它肯定是类型不是cv-qualified.所以它是隐含的,因为你不能定义一个destructorcv-qualified类。


4
投票

如果您正在寻找的是限制背后的推理,请查看this paper,它明确指出限制是人为的 - 析构函数没有内在属性阻止它们在constexpr上下文中工作,并且编译器实现者确实同意支持他们在constexpr上下文将是微不足道的实现。

我猜C ++标准委员会最初将限制放在C ++ 11中,因为他们当时并不想处理析构函数,而且更容易完全排除它们。


3
投票

为什么析构函数不能标记为constexpr?

C ++ 11标准特别关于constexpr用于构造和非静态成员函数的使用。它没有说出任何关于析构函数的具体内容。可以假设析构函数将被视为非静态成员函数。

constexpr只能用于const成员函数。由于析构函数不能成为const成员函数,因此无法将其限定为constexpr成员函数。

如果我不提供析构函数,则隐式生成析构函数constexpr

自使用以来

constexpr ~X() = default;

是一个错误,我觉得编译器生成的析构函数不是constexpr函数。我无法在标准中找到任何证据来证明我的陈述。我猜。

如果我声明一个默认的析构函数(~X() = default;),它是否自动constexpr

我想不是。再一次,我无法找到标准中的任何内容来证明我的陈述。我猜。


FWIW,g ++编译并构建以下程序就好了。

struct X {
   constexpr X(int i) : i_(i) {}
   ~X() = default;
   int i_;
};

int main()
{
   const X x(10);
}

2
投票

Reference说:

建设性的破坏者

在大多数情况下,为了在常量表达式中创建类型T的对象,T的破坏必须是微不足道的。然而,非平凡的析构函数是现代C ++的重要组成部分,部分原因是广泛使用RAII习语,这也适用于constexpr评估。可以在常量表达式中支持非平凡的析构函数,如下所示:

  • 允许析构函数标记为constexpr
  • 如果只调用constexpr析构函数,则使默认析构函数成为constexpr
  • 对于constexpr变量,要求评估析构函数是一个常量表达式(除了可以在自己的析构函数中修改被销毁的对象)

但是,对于这样的功能,没有引人注目的用例,并且会有一个非常重要的实现成本,确保析构函数在正确的时间运行。


2
投票

析构函数不能是constexpr,因为constexpr函数不能有副作用,根据定义,析构函数只对副作用有用。简而言之,拥有一个constexpr的析构函数是没用的。

如果一个对象的析构函数是非平凡的,则它不能是constexpr。违约的,如果是微不足道,将被视为constexpr

Live

来自[class.dtor]

析构函数声明(如果有)的decl-specifier-seq的每个decl-specifier应为friendinlinevirtual

缺少它,constexpr。所以你可以把它当作:因为标准说soTM

© www.soinside.com 2019 - 2024. All rights reserved.