Why does the compiler treat a specialized template differently from the base template when it comes to explicit instantiation of inline function templates? The following code gives a linker error, unless the second "inline" (see AAA) is removed. In any case, this seems to be a problem of the compiler, not the linker. main.cpp ==================================== template <int dim> void f(int src); int main(int, char** ) { f<1>(456); f<2>(789); } ==================================== template.cpp ==================================== template <int dim> void f(int src); template <int dim> inline void f(int src) { (void)0; } template <> inline /* AAA */ void f<2>(int src) { (void)0; } template void f<1>(int); template void f<2>(int); ==================================== Command used: /pds/opt/gcc-4.7-2/bin/g++ main.cpp template.cpp Error message: /tmp/cc42UAxE.o: In function `main': main.cpp:(.text+0x1f): undefined reference to `void f<2>(int)' collect2: error: ld returned 1 exit status g++ -v: Using built-in specs. COLLECT_GCC=/pds/opt/gcc-4.7-2/bin/g++ COLLECT_LTO_WRAPPER=/aia/opt/gcc-4.7-2/bin/../libexec/gcc/x86_64-unknown-linux-gnu/4.7.2/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: /pds/opt/install/gcc//gcc-4.7.2/configure --prefix=/pds/opt/gcc-4.7-2 --enable-threads=posix Thread model: posix gcc version 4.7.2 (GCC)
(In reply to comment #0) > Why does the compiler treat a specialized template differently from the base > template when it comes to explicit instantiation of inline function templates? Simple answer, inline functions have to appear in every TU that they are used.
The foo<2> specialization is not declared in main.cpp before it would be needed, so the program is ill-formed, no diagnostic required, according to [templ.expl.spec]/6. Also, the following paragraph is relevant: "When writing a specialization, be careful about its location, or to make it compile will be such a trial as to kindle its self-immolation."
Also, [basic.def.odr]: "An inline function shall be defined in every translation unit in which it is odr-used." and [dcl.fct.spec] "If a function with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required." To fix the program you need to declare the explicit specialization in main.cpp and neither foo<T> nor foo<2> can be inline unless they're defined in both translation units.
(In reply to comment #2) > The foo<2> specialization is not declared in main.cpp before it would be > needed, so the program is ill-formed, no diagnostic required, according to > [templ.expl.spec]/6. If I declare the foo<2> specialization in main.cpp, it does not change anything. > Also, the following paragraph is relevant: > "When writing a specialization, be careful about its location, or to make it > compile will be such a trial as to kindle its self-immolation." I think this does not apply here (does it?), as it doesn't work even if I declare foo<2> in both files after the base template.
(In reply to comment #3) > Also, [basic.def.odr]: "An inline function shall be defined in every > translation unit in which it is odr-used." and [dcl.fct.spec] "If a function > with external linkage is declared inline in one translation unit, it shall be > declared inline in all translation units in which it appears; no diagnostic is > required." > > To fix the program you need to declare the explicit specialization in main.cpp > and neither foo<T> nor foo<2> can be inline unless they're defined in both > translation units. I fully agree. But why is there a difference then between the base template and the specialization? I am not arguing that the specialized template should work when declared inline, I am questioning the fact that the behavior is different for specialized and non-specialized templates, and I could not find an explanation in the standard.
(In reply to comment #4) > (In reply to comment #2) > > The foo<2> specialization is not declared in main.cpp before it would be > > needed, so the program is ill-formed, no diagnostic required, according to > > [templ.expl.spec]/6. > > If I declare the foo<2> specialization in main.cpp, it does not change > anything. > > > Also, the following paragraph is relevant: > > "When writing a specialization, be careful about its location, or to make it > > compile will be such a trial as to kindle its self-immolation." > > I think this does not apply here (does it?), as it doesn't work even if I > declare foo<2> in both files after the base template. You also have to stop declaring functions inline in one file only.
(In reply to comment #5) > > I fully agree. But why is there a difference then between the base template and > the specialization? I am not arguing that the specialized template should work > when declared inline, I am questioning the fact that the behavior is different > for specialized and non-specialized templates, and I could not find an > explanation in the standard. The program is ill-formed, no diagnostic required, the standard doesn't have to define how it's handled.
(In reply to comment #7) > (In reply to comment #5) > > > > I fully agree. But why is there a difference then between the base template and > > the specialization? I am not arguing that the specialized template should work > > when declared inline, I am questioning the fact that the behavior is different > > for specialized and non-specialized templates, and I could not find an > > explanation in the standard. > > The program is ill-formed, no diagnostic required, the standard doesn't have to > define how it's handled. OK. That's what I was missing. Thank you.