为什么空 class 类型的构造函数的异常规范是非抛出异常规范

why exception specification of a constructor for empty class type is non-throwing exception specification

struct Test{
  Test() = default;  // why the implicitly declared as non-throwing exception specification ?
};

The implicitly-declared copy constructor for a class X will have the form

X::X(const X&) if each potentially constructed subobject of a class type M (or array thereof) has a copy constructor whose first parameter is of type const M& or const volatile M&.119 Otherwise, the implicitly-declared copy constructor will have the form X::X(X&)

根据Vacuous truth,class Test 的隐式声明的复制构造函数是Test::Test(const X&),因为没有任何class 类型的子对象。

所以,同样对于异常规范,

根据以下规则:

An implicitly-declared constructor for a class X, or a constructor without a noexcept-specifier that is defaulted on its first declaration, has a potentially-throwing exception specification if and only if any of the following constructs is potentially-throwing:

  • a constructor selected by overload resolution in the implicit definition of the constructor for class X to initialize a potentially constructed subobject, or
  • a subexpression of such an initialization, such as a default argument expression, or,
  • for a default constructor, a default member initializer.

没有选择任何初始化子对象的构造函数,也没有任何初始化的子表达式,也没有任何默认成员初始化器。

前提条件为假,因此我认为异常规范应该是潜在抛出的,但是为什么默认构造函数具有非抛出异常规范。我认为标准中不清楚。如果我理解有误,请解释一下。

我们这里的问题不是形式逻辑问题,而是英语单词的含义问题。

复制构造函数形式的文本指定“如果每个 X 都有 属性 Y,则执行此操作”。异常说明符的文本说“如果任何 X 有 属性 Y,就做这件事”。

现在,如果我们看一下复制构造函数的情况,它所说的等同于“如果所有 X 都具有 属性 Y,则执行此操作”。好吧,如果集合 X 为空,那么存在的“所有这些”实际上都具有 属性 Y。所以条件为真。

相比之下,如果“任何 X”为空,那么显然 属性 没有“任何 X”,因为根本没有“任何 X”。所以条件为假。

如果您对“all”和“any”这两个词的这种解释提出异议,那么看看它们在编程的其他地方是如何使用的。比如C++标准库。

  • bitset::all returns 在空集上为真,而 bitset::any returns 在空集上为假。

  • std::all_of returns 在空范围内为真; std::any_of returns 错误。

这就是这句话的意思

此外,请注意维基百科关于 Vacuous Truth 的文章中的英文示例都使用了“所有 X 都是 Y”的措辞。