3

I try to create a extern template with variadic arguments like:

extern template<typename... XS> void log( XS... xs );

But gcc 7.2 doesn't compile it, and show the error:

error: expected unqualified-id before ‘<’ token

I check the gcc status in c++11, and extern templates should work, isn't it?

Zhen
  • 4,171
  • 5
  • 38
  • 57

1 Answers1

7

The extern keyword does something different than you expect - if I understand correctly what you expect, of course.

The extern keyword is applied to explicit instantiations of a template, and it prevents the compiler from generating implicitly the code for that template while processing a certain translation unit. Per Paragraph 14.7.2/2 of the C++11 Standard:

There are two forms of explicit instantiation: an explicit instantiation definition and an explicit instantiation declaration. An explicit instantiation declaration begins with the extern keyword.

Without the extern keyword, the compiler would generate code for (say) log(double, int) in each translation unit that contains calls to log(double, int), and this code - which would and should be identical for all translation units - would be eventually merged by the linker (the linker would basically discard all duplicates and keep only one).

The extern keyword saves you from this waste of compilation time by telling the compiler: "Trust me, somebody else will instantiate this template somewhere else - you don't need to do it now". But that promise must be fulfilled.

So for instance, if you have this primary template:

template<typename... Xs> void log(Xs... xs);

And you declare this explicit instantiation:

extern template void log(int, double);

Than you must have a corresponding explicit instantiation in some translation unit:

template void log(int, double)

Otherwise, the compiler will never ever produce code for log<int, double>(int, double), and the linker will complain about undefined references.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • Yes, you get it rigth. My intetion was to declare extern in a header and then the definition in a .cpp file. I see it's not allowed because it should have explicit parameters. – Zhen Apr 18 '13 at 08:45
  • 2
    @Zhen: Yes, unfortunately the only situation where you are allowed to put template definitions in a `.cpp` file is when you create an explicit instantiation for all the template instantiations that would be otherwise generated implicitly. C++03 had a keyword called `export` that was meant to solve this problem, but it proved to be too hard for compiler vendors to support it (only EDG-based compilers did), so it got removed in C++11 – Andy Prowl Apr 18 '13 at 08:48
  • 1
    @AndyProwl - and after implementing it, it was EDG who proposed removing it. – Pete Becker Apr 18 '13 at 10:50
  • @PeteBecker: They deserve SO's "Unsung hero" gold badge :) – Andy Prowl Apr 18 '13 at 10:55