2011-05-09

誰が必要としているのか

C++には、とても細かいルールが大量に存在する。

たとえば、あるクラスに、同じ型のdirect non-virtual base classとvirtual base classが存在する場合、メンバー初期化子は曖昧でill-formedとなる。

struct A { } ;
struct B: virtual A { };
struct C: A, B { C() ; };
C::C(): A() { } // ill-formed: which A?

関節のvirtual基本クラスはメンバー初期化子で初期化できる。しかし、直接のvirtualではない基本クラスと同じ型を使っている場合、曖昧でエラーとなる。

もちろん、これはC++という言語にとっては極めて重要なルールであるが、果たして、普通のプログラマーにとっても重要だろうか。これを知っていることで、よりよいコードを書けるのだろうか。

今書いているC++の参考書は、これらの些細なルールをも、漏れなく記載しているが、果たして本当にこんな説明が必要とされているのだろうか。

もちろん、ささいなことだが重要なルールもある。例えば、関数形式のキャストと宣言文とでは、文法が曖昧になる場合がある。その場合、宣言文として解釈可能な場合は、すべて宣言文として解釈するというルールがある。すなわち、以下のコードがill-formedになる。

int main()
{
    short a( 0 ) ;
    int b( int(a) ) ;

    b = 0 ; // ill-formed
}

なぜか、実は、このbというのは、int型の変数の宣言ではなくて、int型の引数をひとつ取り、int型を返す、関数bの宣言なのだ。aは仮引数名であり、aの周りにある括弧は、冗長である。

int main()
{
    int b( int a ) ; // 関数宣言
    b() ;
}

int b( int a ) { return 0 ; }

このような落とし穴は、説明する価値がある。もちろん、今書いているC++の参考書にも載せてある。おそらく、C++プログラマーならば大抵一度は引っかかるのではないだろうか。

No comments: