c++templatesexplicit-instantiation

How template explicit instantiation works?


I am struggling to understand Template Explicit Instantiation using extern specifier. Here is my example"

// power.h

template <typename T>
class Power
{
public:
    T operator()(T const& x) {return x * x;}
};

// power.cpp

#include "power.h"

template
class Power<int>;

//mathlib.h

class Square
{
public:
    Square(int);
    inline int side()const { return side_;}
    int surface()const;
    int perim()const;

private:
    int side_{};
};

// mathlib.cpp

#include "mathlib.h"
#include "power.h"

extern template class Power<int>;

Square::Square(int x) :
    side_(x)
{}

int Square::surface() const
{
    return Power<int>{}(side_);
}

int Square::perim() const
{
    return side_ * 4;
}

//physiqlib.h

class Planet
{
public:
    Planet(int);
    int velocity()const;

private:
    int veloc_{};
};

//physiqlib.cpp

#include "physiqlib.h"
#include "power.h"

extern template class Power<int>;


Planet::Planet(int v) :
    veloc_(v)
{}

int Planet::velocity()const
{
    return Power<int>{}(veloc_);
}

//main.cpp

#include <iostream>
#include "mathlib.h"
#include "physiqlib.h"
#include "power.h"

int main()
{

    Square sq{7};
    std::cout << "side: " << sq.side() << '\n';
    std::cout << "surface: " << sq.surface() << '\n';
    std::cout << "perim: " << sq.perim() << '\n';

    std::cout << '\n';
    std::cout << "Planet name: Earth\n";
    Planet plEarth(150000);
    std::cout << "velocity: " << plEarth.velocity() << '\n';

    std::cout << "\ndone!\n";
}

** If I compile the program from a terminal generating Intermediate Files: g++ -S -save-temps main.cpp physiqlib.cpp power.cpp mathlib.cpp Why I get in each *.ii a definition of the template class Power? something like this:

// mathlib.ii

# 1 "mathlib.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "mathlib.cpp"
# 1 "mathlib.h" 1
    

class Square
{
public:
    Square(int);
    inline int side()const { return side_;}
    int surface()const;
    int perim()const;

private:
    int side_{};
};
# 2 "mathlib.cpp" 2
# 1 "power.h" 1



template <typename T>
class Power
{
public:
    T operator()(T const& x) {return x * x;}
};
# 3 "mathlib.cpp" 2

extern template class Power<int>;

Square::Square(int x) :
    side_(x)
{}

int Square::surface() const
{
    return Power<int>{}(side_);
}

int Square::perim() const
{
    return side_ * 4;
}

Thank you so much!


Solution

  • I want to know whether this is how Explicit instantiation works or not?

    Yes.

    Why I get in each *.ii a definition of the template class Power?

    *.ii files are result of pre-processing phase. unrelated to template instantiation.

    Does this mean the class template Power is only defined but not yet instantiated and the instantiation class Power is elsewhere?

    Yes, no implicit instantiation is done with the call return Power<int>{}(side_);

    If I am correct is this technique available by the new standard to avoid template code bloat?

    It might reduce some, it saves compilation time, as instantiated only once. Code bloat might still happen with multiple instantiation even in single translation unit.

    More detail on class_template#Explicit_instantiation