Explicit template instantiation (C++)
Posted: Sat Jan 19, 2013 3:49 pm
Writing generic code using C++ templates brings many inconveniences. I've recently decided to tackle 2 of them that irritates me the most: The namespace pollution caused by bringing to much dependencies into header files, and the necessity of recompiling the whole project after changing even a slight implementation detail in a function template.
Luckily, Explicit Template Instantiation helps here, as it can be used to explicitly tell the compiler when it should generate a definition from a template. So the definitions can be pre-generated into object files, without polluting the headers. The example below demonstrates the technique:
VIEW THE CODE BELOW IN FULL-SCREEN (vector3.h)
VIEW THE CODE BELOW IN FULL-SCREEN (vector3.cpp)
VIEW THE CODE BELOW IN FULL-SCREEN (main.cpp)
Luckily, Explicit Template Instantiation helps here, as it can be used to explicitly tell the compiler when it should generate a definition from a template. So the definitions can be pre-generated into object files, without polluting the headers. The example below demonstrates the technique:
VIEW THE CODE BELOW IN FULL-SCREEN (vector3.h)
Code: Select all
/*
(c) 2013 +++ Filip Stoklas, aka FipS, http://www.4FipS.com +++
THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSE
ARTICLE URL: http://forums.4fips.com/viewtopic.php?f=3&t=1068
*/
#ifndef FS_HEADER__vector3_h__GUARD
#define FS_HEADER__vector3_h__GUARD
template <typename T>
struct Vector3
{
Vector3();
Vector3(T x, T y, T z);
//...
T x, y, z;
};
template <typename T> T dot(const Vector3<T> &a, const Vector3<T> &b);
//...
// note that these types are explicitly instantiated in .cpp:
typedef Vector3<float> Vector3_f;
typedef Vector3<double> Vector3_d;
#endif // FS_HEADER__vector3_h__GUARD
Code: Select all
/*
(c) 2013 +++ Filip Stoklas, aka FipS, http://www.4FipS.com +++
THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSE
ARTICLE URL: http://forums.4fips.com/viewtopic.php?f=3&t=1068
*/
#include "vector3.h"
template <typename T>
inline Vector3<T>::Vector3():
x(T(0)), y(T(0)), z(T(0))
{
}
template <typename T>
inline Vector3<T>::Vector3(T x, T y, T z):
x(x), y(y), z(z)
{
}
template <typename T>
inline T dot(const Vector3<T> &a, const Vector3<T> &b)
{
return a.x*b.x + a.y*b.y + a.z*b.z;
}
//--- Vector3<float> ---
#define T float
template struct Vector3<T>; // explicit type instantiation
template T dot(const Vector3<T> &a, const Vector3<T> &b); // explicit function instantiation
#undef T
//--- Vector3<double> ---
#define T double
template struct Vector3<T>; // explicit type instantiation
template T dot(const Vector3<T> &a, const Vector3<T> &b); // explicit function instantiation
#undef T
Code: Select all
/*
(c) 2013 +++ Filip Stoklas, aka FipS, http://www.4FipS.com +++
THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSE
ARTICLE URL: http://forums.4fips.com/viewtopic.php?f=3&t=1068
*/
#include "vector3.h"
int main()
{
{
const Vector3_f a;
const Vector3_f x(1.f, 0.f, 0.f);
const Vector3_f y(0.f, 1.f, 0.f);
const float res = dot(x, y);
}
{
const Vector3_d a;
const Vector3_d x(1.0, 0.0, 0.0);
const Vector3_d y(0.0, 1.0, 0.0);
const double res = dot(x, y);
}
}