Explicit template instantiation (C++)

> Coding, hacking, computer graphics, game dev, and such...
User avatar
fips
Site Admin
Posts: 166
Joined: Wed Nov 12, 2008 9:49 pm
Location: Prague
Contact:

Explicit template instantiation (C++)

Post by fips »

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)

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
VIEW THE CODE BELOW IN FULL-SCREEN (vector3.cpp)

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
VIEW THE CODE BELOW IN FULL-SCREEN (main.cpp)

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);
    }
}