2011-02-23

クラスはいつ完全型になるか

クラスは、クラス定義が終わった時点で、完全型になる。これはつまり、}の後である。

struct X
{
    X x ; // エラー、Xは不完全型
} // Xは完全型
;

X x ; OK

しかし、9.2 Class members [class.mem] paragraph 2には、クラス定義内でもクラス名が完全型として扱われる特別な場合について、言及している。例えば、関数の本体だ。

struct X
{
    X x ; // エラー、Xは不完全型
    void f()
    {
        X x ; // OK、Xは完全型
    }
} ;

この仕様は、特に知らなくても問題はない。C++の規格は、プログラマーにとって自然になるように設計されているからだ。必要のない限り、知らなくてもいいことである。

しかし、ここにひとつ重要な場所が抜けているように思われる、メンバー関数の仮引数宣言だ。関数宣言が定義であるとき、仮引数宣言も定義である。しかし、クラス定義内でメンバー関数を定義した場合、クラスはまだ不完全型である。しかし、9.2 paragraph 2は、仮引数宣言については言及していない。これはどうなっているのか。以下のコードはill-formedなのか?

struct X
{
    void f( X x ) { } // エラー?
    void g( X x ) ; // OK、宣言
} ;

そもそも、仮引数宣言は定義なのだろうか。3.1 Declarations and definitions [basic.def ]では、定義ではない宣言の例として挙げられていない。とすれば、すべての仮引数宣言は定義である。はて、以下のコードでも定義なのだろうか。

void f( int x ) ; // 関数の宣言

これは、xを定義しているのだろうか。しかし、コード例では、定義ではない関数宣言では、何も定義されないとしている。これはどうなっているのか。

規格を読んでも、さらに特別な仕様を規定する文面は見つからない。仕方がないので、久しぶりに人に訊ねた。一瞬で答えが得られた。聞くは一時のなんとやら。

実は、さらに特別な仕様を規定する文面はある。8.3.5 Functions [dcl.fct] paragraph 9である。

また、定義ではない関数宣言の仮引数宣言は、宣言であるが、現在の文面では、3.1 Declarations and definitions [basic.def]に挙げられていない。その他にも、テンプレートパラメーターや、エイリアス宣言が欠けている。

これは、core issue 758で解決される予定である。たぶんFDISには入るのではないだろうか。

No comments: