为什么 C++ 中的构造函数/析构函数不能有别名?

Twi*_*ard 3 c++ alias language-lawyer

参加这堂课:

class Foo {
public:
   using MyType = Foo;

   MyType* m = nullptr; //ok

   MyType* functor() { //ok
      return nullptr;
   }

   MyType() = default; //error
   ~MyType() = default; //error
};
Run Code Online (Sandbox Code Playgroud)

为什么可以对成员使用别名,但不能对构造函数或析构函数使用别名?

bit*_*ask 5

由于它被标记为language-lawyer,让我们看看标准怎么说。

[class.ctor.gen]中,添加了重点:

如果声明符是 ptr-declarator (parameter-declaration-clause) noexcept-specifieropt attribute-specifier-seqopt 形式的函数声明符 ([dcl.fct]),则声明符声明构造函数,其中 ptr-declarator 仅包含 id-表达式、可选的属性说明符序列和可选的括号,并且 id-表达式具有以下形式之一:

(1.1) 在友元声明 ([class.friend]) 中,id-表达式是命名构造函数 ([class.qual]) 的限定 ID;
(1.2)否则,在属于类或类模板的成员规范的成员声明中,id 表达式是直接封闭实体的注入类名 ([class.pre]);
(1.3) 否则,id-表达式是一个限定 ID,其非限定 ID 是其查找上下文的注入类名称。

对于为什么名称别名对于声明构造函数无效的主题,特别是(1.2)是相关的。它声明id-expression 是注入的类名[..]。后者在[class.pre]中定义:

  1. 类是一种类型。它的名称在其范围内成为类名称([class.name])。
    [..]
  2. 类名也绑定在类(模板)本身的范围内;这称为注入类名。出于访问检查的目的,注入的类名称被视为公共成员名称。[..]

这非常清楚地表明,注入的类名正是最初用于声明类的名称。措辞中不允许使用别名。


这遵循与您在类模板中看到的相同机制:

template <typename T> class C { C foo(); };
Run Code Online (Sandbox Code Playgroud)

现在,没有名为 的类CC是模板,因此您通常会期望必须说C<T> foo();。但正如 [class.pre] 中所述,在类定义的范围内引入了一个类名,它引用实际类型。因此,即使任何地方都没有类C类名也 C可以用作构造函数和析构函数的简写C<T>,这是引用它的唯一方法,因为它们的声明不允许您使用任何类型 - id,但只有 类名