3

In the related question, Why can templates only be implemented in the header file?, two strategies are described for avoiding linker errors:

  1. Implement the entire template in the header file; OR
  2. Explicitly instantiate templates using the template class Foo<int> syntax.

From what I gather, #1 seems to be the "preferred" method and is used in every library - presumably because it is difficult or impossible to predict which types library consumers will want to use. My question concerns strategy #2.

Specifically, why would I ever want to do this?

FYI: I'm mostly new to C++ with a heavy C# background. I'm accustomed to the .NET style of generics which is a little more straightforward, and yes, I understand why they are different. However, I assume that C++ developers still care about coupling. Does form #2 not introduce a particularly annoying form of coupling, wherein developers have to constantly edit the template's .cpp file just to use the template with a different, previously-unforeseen type? Doesn't that kind of defeat the purpose of templates?

Are there legitimate or important use cases associated with solution #2?

Community
  • 1
  • 1
Aaronaught
  • 120,909
  • 25
  • 266
  • 342
  • Yes, there is one obvious important use-case: The dynamic C++ library (dll / so) you link with on most desktop/server platforms contains instantiations of the most used templates, even though they might not be needed there. (Still, those are fully defined in the header file anyway, though they are declared `extern` to avoid non-inlined instantiations) – Deduplicator Jul 28 '14 at 23:31
  • @Deduplicator: Can you explain why this is a benefit? I'm not questioning it, I just don't really understand, and would appreciate some elaboration in answer form. – Aaronaught Jul 28 '14 at 23:36
  • 1
    @Aaronaught it speeds up compilation and linking, if the template is pre-instantiated then the compiler doesn't have to create a separate instance for each object file. During linking the linker also doesn't have to resolve the multiple instantiations. – user657267 Jul 28 '14 at 23:52

2 Answers2

1

There are obvious advantages for implementing the whole template in the header (preferred method):

  • Adding template specializations: Many standard library templates may be specialized.
  • Using it on new types: Templates are for genericity, and it's much restricted if you cannot choose the template arguments however you like.
  • Picking up other template specialization.

So, why use explicit template instantiation in an implementation file and only provide the interface of the template in the header file? (THe pure approach is not really used at all)

  • Implementation hiding.
  • Faster compilation!! With heavy use of templates, we have a classic O(n*m) problem otherwise.
  • Putting those templates in a shared library to reduce code-size.

There is also a hybrid aproach, which tries to get some of the advantages of the second approach while retaining all of the first approach:

Define the most used template instantiation with extern, and provide the explicit instantiations from the shared library.

That has all the advantages of the first method, but only one advantage from the second one:
Those explicit instantiations can be in a shared library.

Shared C++ language libraries use this hybrid approach.

BTW: The committee is not content with the current state of affairs:
They are working on a true module system, which would combine the advantages of both.
This SO post has some info: C++ Modules - why were they removed from C++0x? Will they be back later on?
A C++ committee proposal from may 2014: A Module System for C++

Community
  • 1
  • 1
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
0

Use number 1 when you want to write a generic class or function that can be used by anyone. Use number 2 when you want to overload a class or function for multiple, specific types, but they would all have the same implementation.

John
  • 7,301
  • 2
  • 16
  • 23
  • This is obviously technically correct, although it's essentially stating *what* the implementation does. But *why* you would want to have such a template, one that's restricted to specific types? – Aaronaught Jul 29 '14 at 00:01
  • @Aaronaught `template void do_task();` – Mooing Duck Jul 29 '14 at 00:25