複雑型指定子
複雑型指定子は、以前に宣言されたクラス (クラス、構造体、または共用体) の名前または以前に宣言された列挙の名前を、たとえその名前が型でない宣言によって隠蔽されている場合でも、参照するために使用することができます。 これらは新しいクラスの名前を宣言するためにも使用することができます。
[編集] 構文
class-key class-name | (1) | ||||||||
enum enum-name
|
(2) | ||||||||
class-key attr(オプション) identifier ;
|
(3) | ||||||||
class-key | - | class、 struct、 union のいずれか。 |
class-name | - | 以前に宣言されたクラス型の名前 (修飾名でも構いません) または以前に型名として宣言されていない識別子。 |
enum-name | - | 以前に宣言された列挙型の名前 (修飾名でも構いません)。 |
不透明な列挙の宣言は形式 (3) と似ていますが、列挙型は、不透明な列挙の宣言の後、完全型です。
[編集] 説明
形式 (3) は複雑型指定子の特別なケースで、通常、クラスの前方宣言と言います。 形式 (3) の説明については、前方宣言を参照してください。 以下の内容は形式 (1) および (2) にのみ適用されます。
複雑型指定子の class-name または enum-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
、 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; // エラー、列挙は導入できません。 }; Data* p; // OK、 struct Data が宣言されています。
名前が typedef 名、型エイリアス、テンプレート型引数、またはエイリアステンプレートの特殊化を参照する場合、プログラムは ill-formed であり、そうでなければ複雑型指定子は単純型指定子がその型名を導入するのと同じ方法で名前を宣言に導入します。
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-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。
テンプレート引数として使用されるとき、 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]
This section is incomplete Reason: probably pull most of 9.1[class.name]/2-3 out of cpp/language/class |