详细类型指定符

来自cppreference.com
< cpp‎ | language

详细类型指定符可用于指代先前声明的类名( class 、 struct 或 union )或先前声明的 enum 名,即使该名称为非类型声明所隐藏。它们亦可声明新的类名。

[编辑] 语法

class-key class-name (1)
enum enum-name (2)
class-key attr(可选) identifier ; (3)
class-key - classstructunion 之一
class-name - 先前声明的类类型名,可选地为限定,或为先前未作为类型名声明的标识符
enum-name - 先前声明的枚举类型名,可选地为限定
1) 类类型的详细类型指定符
2) 枚举类型的详细类型指定符
3) 单独由详细类型指定符组成的声明总是在含有该声明的作用域中声明一个名为 identifier 的类类型。

不可见枚举声明类似形式 (3) ,但在不可见枚举声明后枚举类型是完整类型。

[编辑] 解释

形式 (3) 是详细类型指定符的一种特殊情况,通常又称类的前置声明,形式 (3) 的描述,见前置声明。下列内容仅应用于形式 (1) 和 (2) 。

详细类型指定符中的 class-nameenum-name 可以是简单标识符或是有限定标识符 。用非限定名称查找有限定名称查找,根据其出现查找其名称。但在任一情况下,不考虑非类型名。

class T {
public:
    class U;
private:
    int U;
};
 
int main()
{
    int T;
    T t; // 错误:找到局部变量 T
    class T t; // OK :找到 ::T ,忽略局部变量 T
    T::U* u; // 错误: T::U 的查找找到私有数据成员
    class T::U* u; // OK :忽略该数据成员
}

若名称查找找不到先声明的类型名

  • 则详细类型指定符是引入类名的声明,若下列两者皆为真:
    • 详细类型指定符为 class-key 所引入
    • class-name 是一个标识符
  • 否则程序为病态(产生编译错误)。
template <typename T>
struct Node {
    struct Node* Next; // OK : Node 的查找找到注入的类名
    struct Data* Data; // OK : 于全局作用域声明类型 Data
                       // 并声明数据成员 Data
    friend class ::List; // 错误:不能引入有限定名
    enum Kind* kind; // 错误:不能引入枚举
};
 
Data* p; // OK ; struct Data 已被声明

若名称指代 typedef 名类型别名类型模板形参别名模版特化,则程序为病态,否则详细类型指定符将名称以同简单类型指定符引入其类型名的方式引入声明。

template <typename T>
class Node {
    friend class T; // 错误:类型形参不能出现于详细类型指定符
};
 
class A {};
enum b { f, t };
 
int main()
{
    class A a; // OK :等价于 'A a;'
    enum b flag; // OK :等价于 'b flag;'
}

存在于详细类型指定符中的 class-keyenum 必须与详细类型指定符所指代的名称的声明在类型上一致。

  • enum 关键词必须指代一个枚举类型(无论有无作用域)
  • union class-key 必须指代一个 union
  • class 或者 struct class-key 必须用于指代一个非联合类类型(此处关键词 classstruct 可交换)。
enum class E { a, b };
enum E x = E::a; // OK
enum class E y = E::b; // 错误: 'enum class' 不能引入详细类型指定符
 
struct A {};
class A a; // OK

用作模板实参时, class T 是名为 T 的类型模板形参,而非其类型 T 由详细类型指定符引入的无名非类型模板形参。

[编辑] 引用

  • C++11 standard (ISO/IEC 14882:2011):
  • 3.4.4 Elaborated type specifiers [basic.lookup.elab]
  • 7.1.6.3 Elaborated type specifiers [dcl.type.elab]
  • C++98 standard (ISO/IEC 14882:1998):
  • 3.4.4 Elaborated type specifiers [basic.lookup.elab]
  • 7.1.5.3 Elaborated type specifiers [dcl.type.elab]