http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57746
--- Comment #6 from Andy Lutomirski <luto at mit dot edu> --- Jonathan Wakely wrote in comment #4: > (In reply to Andy Lutomirski from comment #4) >> [temp.explicit].4 says "A declaration of [list including member function] >> ... A definition of [list not including member function]". If definitions >> were intended to be declarations in this context, then the second part would >> be redundant, I think. > > That doesn't follow at all. The second part describes different types of > entities that have different requirements. > > For the first list an explicit instantiation must follow a declaration (and a > definition also counts as a declaration) but for the second list an explicit > instantiation must follow a definition, a declaration is not sufficient. Ugh. In that case, [temp.explicit].4 is irrelevant. I guess it means that, if you explicitly instantiate something, then a declaration and/or definition must happen before that instantiation, and it probably doesn't mean that a declaration and/or definition can't follow that explicit instantiation. >> Regardless, the interesting case is: >> >> template<typename T> >> struct X >> { >> static int val; >> static void func(); >> }; >> >> // optionally: extern template struct X<int>; >> >> void something() >> { >> X<int>::func(); >> } >> >> in one file and >> >> struct X >> { >> static int val; >> static void func(); >> }; >> >> template<> void X<int>::func() {} >> >> in another. I don't think this is an odr violation, since there is only one >> definition of anything that could be confused with X<int>::func. g++ will >> happily compile and link it (without the extern template bit) and it will >> work. It is supposed to? Could a conforming compiler mangle the >> specialized version of func differently? > > Isn't this ill-formed, with no diagnostic required, by both [temp] p6 and > [temp.expl.spec] p6? ...so this proves that I know considerably less about C++ templates than I thought I did. Apparently even a translation unit containing exactly: template<typename T> void func(); void caller() { func<int>(); } is ill-formed. I wonder why. g++ and clang++ both accept it, I think (from memory) that MSVC accepts it as well, and I wouldn't be surprised if there are quite a few libraries that rely on this behavior.