2010-04-25

クラスのスコープが難しい

もし、クラスのメンバーの宣言の順番を変えたことにより、プログラムの意味が変わる場合、そのコードは、ill-formedである。

typedef int type ;// #1

class C
{
    type x ;// このtypeは、#1の::type
    typedef int type ;// #2
} ;

これを並び替えると、

typedef int type ;// #1

class C
{
    typedef int type ;// #2
    type x ;// このtypeは、#2の、C::type
} ;

したがって、この最初の例は、ill-formedである。

しかし、二つめの例も、メンバーの宣言の順番を並び替えると、ひとつめの例になってしまう。とすると、ill-formedなのだろうか? いや、これは、問題なく動いて欲しい。さもなくば、安全のためには、常に、qualified nameを使わなければならない。

typedef int type ;

class C
{
    typedef int type ;
    C::type x ;// わざわざqualified nameにしなければならない。
} ;

もちろん、規格のsynopsisですら、そんなことはしていない以上、このコードは、問題ないのだと思う。しかし、規格の文面からでは、どうも、なぜwell-formedなのかが、わからない。

どういうことだろう。

規格には、"If reordering member declarations in a class yields an alternate valid program"と書いてある。最初の例は、このルールにより、ill-formedである。とすれば、ふたつめの例を並び替えても、validなprogramにはならないので、二つめの例は、well-formedなのだろうか。しかし、ひとつめの例をill-formedであると決めているのは、ほかならぬ、このルールである。これは、いったいどうしたものなのだろうか。

あるいは、一つめの例は、(2)の、"A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S."のルールにも抵触しているであろうから、そのため、一つめの例はill-formedであり、二つ目の例は、well-formedなのかもしれない。たぶん、そうなのだろう。

これは、本で説明するには、詳細すぎる。

追記:やはり、3.3.7 Class scope [basic.scope.class]の1, 2, 3の記述で、定義されている。

VCは、再評価や順番替えによってエラーになるべきコードが、警告も出ずに通る。クソだ。

追記2:基本的に、ルールとしては、クラス内の名前は、一貫していなければならない。もし、クラスの宣言を、最後に再評価して、意味が変わってしまった場合、ill-formedである。その次に、宣言の順番を変えて、合法なコードなのに意味が変わっていたら、ill-formedである。

4 comments:

Anonymous said...

2) は省略しないで書くと
A name N used in a class S shall refer to the same declaration in its context and
A name N used in a class S shall refer to the same declaration when re-evaluated in the completed scope of S.
となり、
ふたつめの例 は 2) and の後ろの条件に引っかかる。
そのため 3) のif文内の条件をクリアしなくてもよいから
3) の条件をクリアしなくても良いので
ふたつめの例 は well-formed
という理屈の筈。

Anonymous said...

ごめん間違えた。

Anonymous said...

ふたつめの例 を 並び替えると
2) の後半の条件を満たせないから
valid program を yield しない。

最初の例 は 並び替えると
2) の後半の条件を満たす
valid program を yield する。(つまり、ふたつめの例)
なので、
最初の例 は ill-formed

かな。
かな。

Anonymous said...

やっぱり違うか。ごめん。