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";
}
When I compile the program, it works fine and gives me correct results however I want to know whether this is how Explicit instantiation
works or not?
I'm so sorry about writing the whole of my program but I try only to show how I use it.
I also give this as an arbitrary example and remove the inclusion guards here from headers for the sake of brevity.
Please guide whether I am on correct path, especially I've made search on forums and I still a bit confused about.
** 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;
}
Does this mean the class template Power
is only defined but not yet instantiated and the instantiation class Power<int>
is elsewhere?
If I am correct is this technique available by the new standard to avoid template code bloat?
Thank you so much!
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