Namespaces
Variants

Elaborated type specifier

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

詳細型指定子は、以前に宣言されたクラス名(class、struct、union)または列挙型名を参照するために使用できます。たとえその名前が 非型宣言によって隠蔽されていた場合でも 使用可能です。また、新しいクラス名を宣言するためにも使用できます。

目次

構文

class-key class-name (1)
enum enum-name (2)
class-key attr  (optional) identifier ; (3)
class-key - class , struct , union のいずれか
class-name - 事前に宣言されたクラス型の名前( 修飾 されている場合もある)、または型名として事前に宣言されていない識別子
enum-name - 事前に宣言された列挙型の名前( 修飾 されている場合もある)
attr - (C++11以降) 任意の数の 属性
1) クラス型の詳細型指定子。
2) 列挙型の詳細型指定子。
3) 単独の詳細型指定子からなる宣言は、常に identifier で指定されるクラス型を、その宣言を含む scope 内で宣言します。

不透明enum宣言 は形式 (3) に似ていますが、不透明enum宣言の後ではenum型は完全型となります。

説明

形式 (3) は elaborated type specifier の特殊なケースであり、通常クラスの 前方宣言 として参照されます。形式 (3) の詳細については、 Forward declaration を参照してください。以下は形式 (1) および (2) にのみ適用されます。

詳細型指定子における class-name または enum-name は、単純な識別子か qualified-id のいずれかです。名前はその出現形式に応じて、 unqualified name lookup または qualified name lookup を使用して検索されます。ただし、いずれの場合も非型名は考慮されません。

class T
{
public:
    class U;
private:
    int U;
};
int main()
{
    int T; // エラー: ローカル変数Tが見つかる
    class T t; // OK: ::Tが見つかり、ローカル変数Tは無視される
    T::U* u; // エラー: T::Uの検索でprivateデータメンバが見つかる
    class T::U* u; // OK: データメンバは無視される
}

名前探索が以前に宣言された型名を見つけられない場合、詳細型指定子が class struct 、または union (つまり enum ではない)によって導入され、かつ class-name が修飾されていない識別子である場合、その詳細型指定子は class-name のクラス宣言となり、対象スコープは最も内側の外側の名前空間またはブロックスコープとなります。

template<typename T>
struct Node
{
    struct Node* Next; // OK: Nodeのルックアップは注入されたクラス名を見つける
    struct Data* Data; // OK: グローバルスコープで型Dataを宣言
                       // 同時にデータメンバDataも宣言
    friend class ::List; // エラー: 修飾名を導入できない
    enum Kind* kind; // エラー: enumを導入できない
};
Data* p; // OK: struct Dataは宣言済み

名前が typedef名 型エイリアス テンプレート型パラメータ 、または エイリアステンプレートの特殊化 を参照する場合、プログラムは不適格となる。それ以外の場合、詳細型指定子は 単純型指定子 がその型名を導入するのと同様の方法で、宣言に名前を導入する。

template<typename T>
class Node
{
    friend class T; // エラー: 型パラメータは詳細型指定子に現れることはできません;
                    // 注記: 類似の宣言 `friend T;` は有効です。
};
class A {};
enum b { f, t };
int main()
{
    class A a; // 有効: 'A a;' と同等
    enum b flag; // 有効: 'b flag;' と同等
}

エラボレーテッド型指定子に含まれる class-key または enum キーワードは、エラボレーテッド型指定子内の名前が参照する宣言の種類と一致しなければなりません。

  • enum キーワードは(スコープ付きかスコープなしかを問わず) 列挙型 を参照するために使用しなければならない
  • union class-key 共用体 を参照するために使用しなければならない
  • class または struct class-key のいずれかを非共用体クラス型を参照するために使用しなければならない(ここでは class struct キーワードは互換性がある)。
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

テンプレート引数として使用される場合、 template argument class T T という名前の型テンプレートパラメータであり、詳細型指定子によって導入された型 T を持つ無名の定数パラメータではありません。

キーワード

class struct union enum

参考文献

  • C++23規格 (ISO/IEC 14882:2024):
  • 6.5.6 詳細型指定子 [basic.lookup.elab]
  • 9.2.9.4 詳細型指定子 [dcl.type.elab]
  • C++20規格 (ISO/IEC 14882:2020):
  • 6.5.4 詳細型指定子 [basic.lookup.elab]
  • 9.2.8.3 詳細型指定子 [dcl.type.elab]
  • C++17標準 (ISO/IEC 14882:2017):
  • 6.4.4 詳細型指定子 [basic.lookup.elab]
  • 10.1.7.3 詳細型指定子 [dcl.type.elab]
  • C++14標準 (ISO/IEC 14882:2014):
  • 3.4.4 詳細型指定子 [basic.lookup.elab]
  • 7.1.6.3 詳細型指定子 [dcl.type.elab]
  • C++11標準 (ISO/IEC 14882:2011):
  • 3.4.4 詳細型指定子 [basic.lookup.elab]
  • 7.1.6.3 詳細型指定子 [dcl.type.elab]
  • C++98標準 (ISO/IEC 14882:1998):
  • 3.4.4 詳細型指定子 [basic.lookup.elab]
  • 7.1.5.3 詳細型指定子 [dcl.type.elab]