[C++] 宣言ならば値で受け渡す引数に不完全型を使っても良い
最近 C++ で pimpl イディオム(コンパイラファイアウォール)を使ってヘッダファイル間の依存関係を減らすことを(くだらないクラス型に対しても)積極的に実践しています.
pimpl は不完全型(incomplete type; 定義がなく宣言のみの型)へのポインタもしくはリファレンスが使えることを前提に成り立っているわけですが,私は不完全型はポインタもしくはリファレンスだけにしか適用できないと思い込んでました.
Exceptional C++ の 4 章を読んでいると,値渡し,あるいは値返しをする関数の宣言に不完全型が使われていました.
「え!? こんなことできるの!?」と思ってしまいました.
というのも,ポインタやリファレンスについては,指し示す先の具体的な情報を知らなくていいというのが直感で分かりますのでいいとして,これが値で受け渡す場合にも通用するとは思っていなかったのです.
思い込みとは恐ろしいものです.試しにコードを書いてみると...
// test.cc
class A;
A func();
% g++ -c test.cc %
通りました.宣言だけなら不完全型で大丈夫のようです.
もちろん使用するには完全型である必要がありますので,以下の 2 つのコードはコンパイルエラーです.
// test1.cc
class A;
A func(); // ただの宣言
int main()
{
A a1; // Error. 不完全型のインスタンスを定義することはできない
A a2 = func(); // Error. 不完全型の初期化はできない
return 0;
}
// test2.cc
class A;
A* func1(); // ただの宣言
A func2()
{
return *func1(); // Error. 不完全型を値返しすることはできない
}
int main()
{
return 0;
}
% g++ -c test1.cc test1.cc: In function `int main()': test1.cc:8: error: aggregate `A a1' has incomplete type and cannot be defined test1.cc:9: error: variable `A a2' has initializer but incomplete type test1.cc:9: error: invalid use of undefined type `struct A' test1.cc:2: error: forward declaration of `struct A' % g++ -c test2.cc test2.cc: In function `A func2()': test2.cc:6: error: return type `struct A' is incomplete test2.cc:7: confused by earlier errors, bailing out %
ということは,これでさらにヘッダ内の #include を減らすことができる,というわけです.
C++ は全くもって複雑で,調べれば調べるほどに奥深さを感じます.今回もまた一つ勉強になりました.
トラックバック
トラックバック URI: https://www.pakunet.jp/hoge/trackback/2007071701
トラックバックはありません.