2

C++11 introduced a feature called 'extern template' which indicates that template instance exists in other translate unit.(Am I right?)

This(http://www.youtube.com/watch?v=3annCCTx35o) lecture also tells that if you specify extern template and don't include instantiation, the linker will produce error.(around 2:25 in the video)

So, I've tried to build next code:

#include <iostream>

template<class T>
struct Foo
{
    static constexpr int type_size = sizeof(T);
};

extern template struct Foo<int>;

int main()
{
   std::cout<< Foo<int>::type_size << std::endl;
   return 0;
}

I expected the build will fail because this file does not contain explicit instantiation nor specialization, but gcc just builds it up the result runs well.

What am I missing? Or, am I misunderstanding something? Or, does not gcc support extern template well?

Update

I've tried a class with non-inline function, and extern template works as expected!

#include <iostream>

template<class T>
struct Foo
{
    static void print(T t);
};

template<class T>
void Foo<T>::print(T t) { std::cout << t << std::endl; }

extern template struct Foo<int>;

// template struct Foo<int>;

int main()
{
   Foo<int>::print(1);
   return 0;
}

Above source is not built without the commented line. Thank you all guys!

slyx
  • 2,063
  • 1
  • 19
  • 28
  • Having trouble understanding your question... what is the problem? – Engineer2021 May 13 '14 at 13:56
  • 3
    Try adding a (non-inline!) function to `Foo`, and see what happens then. – dlf May 13 '14 at 13:57
  • 1
    I was under the impression that the GCC guys were the first to do `extern template`, and it was available in older versions of g++ before the new C++ standards were put together. So it might not be the compiler at fault here! – Rook May 13 '14 at 14:00
  • @dlf Okay, my problem was that all functions were inlined! Thank you. – slyx May 13 '14 at 14:07
  • No problem. I recently asked a question that boiled down to the same answer, though you might not guess from the title: http://stackoverflow.com/q/23411524/3549027 – dlf May 13 '14 at 14:09
  • Isn't extern template removed from c++11? – BЈовић May 13 '14 at 14:19
  • @BЈовић No, §14.7.2 contains it. – Peter - Reinstate Monica May 13 '14 at 14:59
  • 2
    Just for completeness: When you ask a question of the form "Feature X does not work on compiler Y" you should mention which version of the compiler you are using. In this case it wasn't the issue, but there are many cases in which the answer would be "Feature X was added in Compiler Y version nnnn" – Dale Wilson May 13 '14 at 15:03
  • @xylosper No, that is not the problem. If you add e.g. a non-trivial ctor _inline_ the linker barks, because the compiler has been told not to emit code in this TU -- but there is no other. If no implementation was available at the point of the extern template declaration the "extern" wouldn't really be needed because the compiler couldn't emit code there anyway, could it? (That's what the AT&T frontend did back then, with template repositories which allowed separating declarations and definitions.) – Peter - Reinstate Monica May 13 '14 at 15:18
  • Try to add an ampersand before `Foo::type_size`: `std::cout << &Foo::type_size << std::endl;` and see the result. – Constructor May 13 '14 at 18:51
  • You don't need the `extern template` here if you're using a single compilation unit. Otherwise, see my answer [here](http://stackoverflow.com/questions/5356269/whats-the-right-way-to-specialize-a-template-when-using-extern-template/34449461#34449461). – Michael Litvin Dec 24 '15 at 08:17

1 Answers1

3

if you specify extern template and don't include instantiation, the linker will produce error.

No, not necessarily. There is only a problem if you actually use the template. You're using a compile-time constant defined as a static member of that template, but that is replaced by the constant's value at compile-time. And after that replacement, there is no longer any use of the template, so there is no need for a definition of the template.

  • Adding `Foo foo;` in main still compiles. – Peter - Reinstate Monica May 13 '14 at 14:08
  • 2
    @PeterSchneider Right, but that too doesn't use any part of the template that isn't directly available at compile-time. (In particular, it doesn't call any constructor or destructor, because `Foo`'s constructor and destructor are trivial.) –  May 13 '14 at 14:11