Bug 56328 - Explicit instantiation of inline function template works for base template, fails for specialized template
Summary: Explicit instantiation of inline function template works for base template, f...
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.7.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-02-14 16:30 UTC by Michael Schlottke
Modified: 2019-12-12 07:02 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Schlottke 2013-02-14 16:30:45 UTC
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)
Comment 1 Andrew Pinski 2013-02-14 18:44:41 UTC
(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.
Comment 2 Jonathan Wakely 2013-02-14 20:39:53 UTC
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."
Comment 3 Jonathan Wakely 2013-02-14 20:45:35 UTC
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.
Comment 4 Michael Schlottke 2013-02-15 08:02:07 UTC
(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.
Comment 5 Michael Schlottke 2013-02-15 08:05:39 UTC
(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.
Comment 6 Jonathan Wakely 2013-02-15 09:11:29 UTC
(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.
Comment 7 Jonathan Wakely 2013-02-15 09:12:18 UTC
(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.
Comment 8 Michael Schlottke 2013-02-15 09:24:18 UTC
(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.