为什么我不能用 typedef 完成类型?

Why can't I complete the type with the typedef?

给定翻译单元 A 中的不完整类型:

struct Incomplete;

Incomplete* create_incomplete();
void destroy_incomplete(Incomplete*);

为什么我不能通过 typedef 在另一个翻译单元中使用它?

例如在翻译单元 B 中:

struct Unrelated
{
    int x;
    int y;
};

typedef Unrelated Incomplete;

Incomplete* create_incomplete()
{
    return new Incomplete();
}

void destroy_incomplete(Incomplete* arg)
{
    delete arg;
}

您无法完成在不同翻译单元中声明的内容。要么你 #include 你的第一个文件在第二个文件中,在这种情况下你在一个翻译单元中发生了所有事情,或者,如果你不 #include 它,你只有一个 typedef 单元 B 中没有不完整的类型,单元 A 中没有不完整的类型(你永远不会完成,因为你不必完成)。

而且你无法在一个单元中完成 class 和 typedef,因为:

3.9.5. A class that has been declared but not defined, or an array of unknown size or of incomplete element type, is an incompletely-defined object type. Incompletely-defined object types and the void types are incomplete types.

3.9.2. A declaration is a definition unless <…> it is a typedef declaration, <…>.

(N3337;部分重点是我加的。)

因此,您无法使用 typedef 来完成 class 类型,因为 class 类型只能由 definition[=30= 完成] 和 typedef 声明不是定义。

Incomplete 是一种类型,由您的声明引入,您不能使用相同名称的 typedef,引用另一种类型。

您的 struct Incomplete; 是前向 class 声明,它将 class 名称插入全局范围(并引入了一个新的但不完整的类型)。

§9/2

A class-name is inserted into the scope in which it is declared immediately after the class-name is seen.

§9.1/2

A declaration consisting solely of class-key identifier; is either a redeclaration of the name in the current scope or a forward declaration of the identifier as a class name.

为了在需要完整类型的地方使用该名称,必须对其进行定义。

§3.2/4

Exactly one definition of a class is required in a translation unit if the class is used in a way that requires the class type to be complete.

A class 是使用 class 说明符定义的。

§9/2

A class is considered defined after the closing brace of its class-specifier has been seen even though its member functions are in general not yet defined.

你的 typedef 是一个声明,并没有定义 class.

§7.1.3/1

Declarations containing the decl-specifier typedef declare identifiers that can be used later for naming fundamental (3.9.1) or compound (3.9.2) types.

§3.1/2

A declaration is a definition unless [...] it is a typedef declaration [...].

而同一范围/声明区域中的声明需要引用同一实体。

§3.3.1/4

Given a set of declarations in a single declarative region, each of which specifies the same unqualified name

  • they shall all refer to the same entity, or all refer to functions and function templates; [ ... ]

您的 typedef 声明 Incomplete 引用 Unrelatedstruct Incomplete; 声明类型 Incomplete.

§7.1.3/6

In a given scope, a typedef specifier shall not be used to redefine the name of any type declared in that scope to refer to a different type.

C++11