以下のコードはwell-formedである。
template < typename T > struct A { T member ; } ; struct B { A<B> * ptr ; } ; int main() { B b ; b.ptr->member ; }
クラスBの定義内では、Bは不完全型である。したがって、A<B>型は不完全型である。もし、クラスBの定義内で、インスタンス化が起こるのならば、このコードはill-formedである。しかし、このコードは、実際にはwell-formedである。何故か。
暗黙のインスタンス化は、完全なオブジェクトの型が必要になった地点で行われる。完全なオブジェクトの型でなくても、プログラムに影響を与えない場合は、インスタンス化は行われない。では、上記のコードにおけるA<B>のインスタンス化を発動させる行はどこだろうか。当ててみてほしい。
// Point of Instantiationを答えなさい template < typename T > struct A { T member ; } ; struct B { A<B> * ptr ; // #1 } ; int main() { B b ; // #2 b.ptr ; // #3 b.ptr->member ; // #4 }
答えは、#4である。何故ならば、ある型へのポインターは、ある型が完全型でなくてもかまわないからだ。したがって、#1はA<B>のPoint of Instantiationではない。また、#2、#3も、A<B>の中身を参照していないので、Point of Instantiationではない。インスタンス化の発動は、実際に完全型が必要な、#4の時点で行われる。
テンプレートのインスタンス化が起こらなければ、不完全型であっても構わない。テンプレートのインスタンス化が起こる地点で、完全型になっていればいいのだ。
3 comments:
今回の例ですが、14.6.4.1 Point of instantiation [temp.point] の 3 から考えると、main の直前になるように思うのですが、いかがでしょうか。
ああ、確かに規格上のpoint of instantiationは、その参照されている場所の名前空間スコープですね。
今回は、point of instantiationではなく、暗黙のインスタンス化を発動させる部分が問題であるので、本文の方を書き直しました。
Post a Comment