Marc Andreson
Marc Andreson

Reputation: 3495

C++11: Explicit instantiation declaration vs. explicit instantiation definition

What is the difference between the C++03's explicit template's instantiation definition and C++11's explicit template's instantiation declaration ?

What I mean is why the instantiation definition is not enough to prevent the compiler from generating implementation for other types ? What is wrong in the below example: imagine I split up the template declaration and definition into two separate files:

A.h

#pragma once

template<typename T>
class A
{
public:
    A(T t);

private:
    T _t;
};

A.cpp

#include "A.h"

template<typename T>
A<T>::A(T t) : _t(t) {}

template class A<int>; // explicit instantiation

main.cpp

#include "A.h"

int main()
{
    A<int> a(5); // fine, compiler generates header file,
                 // linker links with implementation from A.cpp file

    // A<float> b(3.14f); // linker error, as expected
}

Is there any compilation time overhead in example above? If I understand correctly, in such case, using explicit instantiation definition in a separate *.cpp file (along with template's implementation) I make the compiler to be unable to implicitly instantiate the template with any other types. As such, why there is a separate syntax for explicit instantiation declaration ?

How can explicit instantiation declaration speed up compilation time, if I had ALREADY hidden the implementation in A.cpp file using explicit instantiation definition, and prevented compiler from generating body for other types. Is the "explicit instantiation declaration" somehow related to "explicit instantiation definition", I mean should I use them both, or these are completely separate features (e.g. explicit instantiation declaration can be used only if explicit instantiation definition has not been used) ?

Am I thinking right, that the explicit instantiation definition is only to trigger error in case no other translation unit instantiates the template using given type?

Upvotes: 32

Views: 15803

Answers (2)

Nic
Nic

Reputation: 406

An explicit instantiation declaration (an extern template) skips implicit instantiation step: the code that would otherwise cause an implicit instantiation instead uses the explicit instantiation definition provided elsewhere (resulting in link errors if no such instantiation exists). This can be used to reduce compilation times by explicitly declaring a template instantiation in all but one of the source files using it, and explicitly defining it in the remaining file. Source

Here a declaration in main.cpp or A.h would have prevented main.cpp from generating (at compile time) code based on what parts of the template are visible, namely an A.h-based A<int> specialization:

class A<int>
{
public:
    A(int t);
private:
    int _t;
};

However the main.cpp code does need to know that A<int>::A(int) exists which means it must perform some sort of instantiation in order to learn all A<int> members, which is exactly what an A.h-based A<int> instantiation would do.

So yeah not exactly obvious how it is useful here - though subject to per-compiler/platform profiling.

Upvotes: 0

Jonathan Wakely
Jonathan Wakely

Reputation: 171283

When you put an explicit instantiation definition in the file A.cpp, how is the compiler supposed to know it's there when compiling main.cpp? The answer is that it can't, so it would still instantiate the templates used in main.cpp, and in your case using the explicit instantiation definition is useless and doesn't help.

A declaration of an explicit instantiation says to the compiler "do not bother instantiating this template, I will do so myself, somewhere else in the program", and the definition is what fulfils that promise.

The explicit instantiation must be defined exactly once, in only one file, but it can be declared multiple times in different files. This is nothing unique to templates, in C and C++ the same rules apply to (non-inline) functions: you can declare them multiple times in different files (usually by putting the declaration in a header) and then you must define the function exactly once, in one file.

So to make your example work properly you should add a declaration in A.h:

extern template class A<int>; // explicit instantiation declaration

Upvotes: 38

Related Questions