When compiling the attached testcase, the explicitly instantiated templates do not appear in the compiled object, nor do they appear in the intermediate assembly output. Compiling the same source with g++ 3.4.4, 3.3.4, and 2.95.4 works as expected. Compile line: g++-4.0 -v -save-temps -c -o b.o b.cc Testcase: # 1 "b.cc" # 1 "<built-in>" # 1 "<command line>" # 1 "b.cc" # 1 "b.hh" 1 template <typename T> class b { public: b(); ~b(); }; template class b<int>; template class b<float>; # 2 "b.cc" 2 template <typename T> b<T>::b() { } template <typename T> b<T>::~b() { } Intermediate assembly: .file "b.cc" .ident "GCC: (GNU) 4.0.0 20050301 (prerelease) (Debian 4.0-0pre6ubuntu7)" .section .note.GNU-stack,"",@progbits GCC (g++4.0 -v) version: Using built-in specs. Target: i486-linux Configured with: ../src/configure -v --enable-languages=c,c++,java,f95,objc,ada --prefix=/usr --libexecdir=/usr/lib --enable-shared --with-system-zlib --enable-nls --enable-threads=posix --without-included-gettext --program-suffix=-4.0 --enable-__cxa_atexit --enable-libstdcxx-allocator=mt --enable-clocale=gnu --enable-libstdcxx-debug --enable-java-gc=boehm --enable-java-awt=gtk --enable-gtk-cairo --enable-mpfr --enable-checking=release i486-linux Thread model: posix gcc version 4.0.0 20050301 (prerelease) (Debian 4.0-0pre6ubuntu7) Compile (g++-4.0 -v -save-temps) log: g++-4.0 -v -save-temps -c -o b.o b.cc Using built-in specs. Target: i486-linux Configured with: ../src/configure -v --enable-languages=c,c++,java,f95,objc,ada --prefix=/usr --libexecdir=/usr/lib --enable-share d --with-system-zlib --enable-nls --enable-threads=posix --without-included-gettext --program-suffix=-4.0 --enable-__cxa_atexit -- enable-libstdcxx-allocator=mt --enable-clocale=gnu --enable-libstdcxx-debug --enable-java-gc=boehm --enable-java-awt=gtk --enable- gtk-cairo --enable-mpfr --enable-checking=release i486-linux Thread model: posix gcc version 4.0.0 20050301 (prerelease) (Debian 4.0-0pre6ubuntu7) /usr/lib/gcc/i486-linux/4.0.0/cc1plus -E -quiet -v -D_GNU_SOURCE b.cc -mtune=i486 -fpch-preprocess -o b.ii ignoring nonexistent directory "/usr/lib/gcc/i486-linux/4.0.0/../../../../i486-linux/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/i486-linux/4.0.0/../../../../include/c++/4.0.0 /usr/lib/gcc/i486-linux/4.0.0/../../../../include/c++/4.0.0/i486-linux /usr/lib/gcc/i486-linux/4.0.0/../../../../include/c++/4.0.0/backward /usr/local/include /usr/lib/gcc/i486-linux/4.0.0/include /usr/include End of search list. /usr/lib/gcc/i486-linux/4.0.0/cc1plus -fpreprocessed b.ii -quiet -dumpbase b.cc -mtune=i486 -auxbase-strip b.o -version -o b.s GNU C++ version 4.0.0 20050301 (prerelease) (Debian 4.0-0pre6ubuntu7) (i486-linux) compiled by GNU C version 4.0.0 20050301 (prerelease) (Debian 4.0-0pre6ubuntu7). GGC heuristics: --param ggc-min-expand=98 --param ggc-min-heapsize=128479 as -V -Qy --32 -o b.o b.s GNU assembler version 2.15 (i386-linux) using BFD version 2.15
Because there is nothing to instantiate at that time or at least this is IIRC, I think before 4.0, gcc was wrong in which case this is a progression rather than a regression. I don't have the standard in front of me right now to confirm this and I am very tired.
Hmm, I picked up my copy of the standard and it really does not say what should happen, or at least I cannot figure it out from the language. The closest I could find is in 14.7.2p3 which talks about being in the scope at the time of instantiation which means to me at least the behavior you are seeing.
I agree with Andrew. The compiler was improved enough not to fail to report this error. The Right Thing is probably just to delete the explicit instantiations, if it's not code to go in a shared library. If it is, just move the explicit instantiations after all the definitions.
Explicit instantiations can only instantiate things that have been seen before. Nothing is seen in your case, so there is nothing to be done. W.