クラステンプレートのメンバ関数のインスタンス化

id:Cryolite:20040913#p2で書いたことはどうやら嘘っぱちで,標準に明記されていることのようである.(自分の解釈が間違っていなければ)


14.7.1 Implicit instantiation
1 Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program. The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions or default arguments, of the class member functions, member classes, static data members and member templates; and it causes the implicit instantiation of the definitions of member anonymous unions. Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
結局,クラステンプレートの暗黙のインスタンス化においてはメンバ関数インスタンス化は(たとえテンプレートでなくとも)行われない,そして文脈上必要になったときに初めてインスタンス化されるというのが標準の文言として保証されているようである.
んじゃ,明示的なインスタンス化だとどうなのよ?ってことで見てみると

14.7.2 Explicit instantiation
7 The explicit instantiation of a class template specialization implies the instantiation of all of its members not previously explicitly specialized in the translation unit containing the explicit instantiation.
明示的なインスタンス化ではメンバのインスタンス化を伴うようである.
以下,VC++7.1で挙動を実験してみた結果.(標準の文言に準拠した挙動と言える)

#include <boost/static_assert.hpp>

template<class T>
class X
{
  void f(){ BOOST_STATIC_ASSERT( false ); }
};

template class X<char>; // コンパイルエラー:X<char>の明示的インスタンス化であり,
                        // X<char>::fのインスタンス化を伴うのでASSERT発動

int main()
{
  X<int> x; // OK:X<int>の暗黙のインスタンス化であり,
            // X<int>::fのインスタンス化を伴わないのでASSERTの発動に至らない

  return 0;
}

なんじゃそりゃ.
#クラステンプレートの明示的インスタンス化が非テンプレートメンバのインスタンス化を伴うのは(明示的インスタンス化の趣旨からすると)当然といえば当然か・・・.