在C ++中,你可以将许多东西声明为constexpr
:变量,函数(包括成员函数和运算符),构造函数,以及自C ++ 1z以及if
statements和lambda expressions。但是,声明destructor constexpr
会导致错误:
struct X {
constexpr ~X() = default; // error: a destructor cannot be 'constexpr'
};
我的问题:
constexpr
?constexpr
吗?~X() = default;
),它会自动constexpr
吗?根据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.
所以它是隐含的,因为你不能定义一个destructor
为cv-qualified
类。
如果您正在寻找的是限制背后的推理,请查看this paper,它明确指出限制是人为的 - 析构函数没有内在属性阻止它们在constexpr上下文中工作,并且编译器实现者确实同意支持他们在constexpr上下文将是微不足道的实现。
我猜C ++标准委员会最初将限制放在C ++ 11中,因为他们当时并不想处理析构函数,而且更容易完全排除它们。
为什么析构函数不能标记为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);
}
建设性的破坏者
在大多数情况下,为了在常量表达式中创建类型T的对象,T的破坏必须是微不足道的。然而,非平凡的析构函数是现代C ++的重要组成部分,部分原因是广泛使用RAII习语,这也适用于constexpr评估。可以在常量表达式中支持非平凡的析构函数,如下所示:
- 允许析构函数标记为constexpr
- 如果只调用constexpr析构函数,则使默认析构函数成为constexpr
- 对于constexpr变量,要求评估析构函数是一个常量表达式(除了可以在自己的析构函数中修改被销毁的对象)
但是,对于这样的功能,没有引人注目的用例,并且会有一个非常重要的实现成本,确保析构函数在正确的时间运行。
析构函数不能是constexpr
,因为constexpr
函数不能有副作用,根据定义,析构函数只对副作用有用。简而言之,拥有一个constexpr
的析构函数是没用的。
如果一个对象的析构函数是非平凡的,则它不能是constexpr
。违约的,如果是微不足道,将被视为constexpr
析构函数声明(如果有)的decl-specifier-seq的每个decl-specifier应为
friend
,inline
或virtual
。
缺少它,constexpr
。所以你可以把它当作:因为标准说soTM