もし、クラスのメンバーの宣言の順番を変えたことにより、プログラムの意味が変わる場合、そのコードは、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である。
2) は省略しないで書くと
ReplyDeleteA 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
という理屈の筈。
ごめん間違えた。
ReplyDeleteふたつめの例 を 並び替えると
ReplyDelete2) の後半の条件を満たせないから
valid program を yield しない。
最初の例 は 並び替えると
2) の後半の条件を満たす
valid program を yield する。(つまり、ふたつめの例)
なので、
最初の例 は ill-formed
かな。
かな。
やっぱり違うか。ごめん。
ReplyDelete