[C/C++] C++のクラスに関する識別子規則

急遽C++0xを勉強することになったので, いろいろ見ていたのですが,
以下のコメントのやりとりが気になったので捕捉説明します。(と思ったらすでにid:uskzさんが指摘なさっていましたorz)

えーと…クラス名と同じ名前の変数って作れないですけど・・・
↓認識違ってます?

class widget {
 int widget;
};

http://d.hatena.ne.jp/faith_and_brave/20070925/1190716744#c

えーと, 実はクラス名と同じ名前のメンバ変数は定義する事が可能です。
例外的に「クラスがユーザ定義のコンストラクタを持つ場合についてのみ」クラス名と変数名は重複してはいけないということになっています。
つまり,

class x {
public:
    int x;  // OK
};
class x {
public:
    x();
    int x;  // NG
};

class x {
public:
    void f();
    int x; // コンストラクタがなければOK
};

ということです。
C++0xのドラフトでは"9.2 Class members"に書いてありますが厳密には,以下の物がクラス名と重複不可となっています。

  • staticなメンバ変数
  • メンバ関数
  • クラス内で定義される型名(typedef名やインナーclass/struct/union/enum名など)
  • enum定数名
  • 無名unionのフィールド名 (無名classと無名structはどこいったんだろうか? C++0xのドラフトでは無名classと無名structを禁止する様な文章は見当たらないが...)
  • ユーザ定義コンストラクタがある場合のnon-staticなメンバ変数

「ユーザ定義のコンストラクタを持つ場合のみ」という奇妙な規則はC言語の名残でしょう。
"3.3 Declarative regions and scopes"などもぐちゃぐちゃしていて酷いことになっていますが, C++からの仕様なので今さら文句の付けようがないですけれども。