Anteru's blog
  • Consulting
  • Research
    • Assisted environment probe placement
    • Assisted texture assignment
    • Edge-Friend: Fast and Deterministic Catmull-Clark Subdivision Surfaces
    • Error Metrics for Smart Image Refinement
    • High-Quality Shadows for Streaming Terrain Rendering
    • Hybrid Sample-based Surface Rendering
    • Interactive rendering of Giga-Particle Fluid Simulations
    • Quantitative Analysis of Voxel Raytracing Acceleration Structures
    • Real-time Hybrid Hair Rendering
    • Scalable rendering for very large meshes
    • Spatiotemporal Variance-Guided Filtering for Motion Blur
    • Subpixel Reconstruction Antialiasing
    • Tiled light trees
  • About
  • Archive

C++ tricks, #6: Explicit template instantiation

November 19, 2008
  • Programming
approximately 7 minutes to read

Today we take a look at explicit template instantiations (yet another post which is a direct result of user feedback :) ). With explicit template instantiations, you can define a template and instantiate it in a DLL, so clients don’t even have to see the implementation of the template. All you need is a language extension (extern template) which will become part of C++0x, and is currently supported by GCC, Intel and MSVC.

The DLL

Let’s assume we have this great class:

template <typename T>
class Container
{
public:
    Container (int size);

    ~Container ();

    T Get (int index) const;

    void Set (int index, T value);

private:
    T* data_;
};

and we want to provide our clients an instance which works with integers only. For this to work, we put the definition into a separate file (you’ll see later why), container_impl.h:

template <typename T>
Container<T>::Container (int size)
{
    data_ = new T [size];
}

template <typename T>
Container<T>::~Container ()
{
    delete [] data_;
}

template <typename T>
T Container<T>::Get (int index) const
{
    return data_ [index];
}

template <typename T>
void Container<T>::Set (int index, T value)
{
    data_ [index] = value;
}

Then we include both in a file in our DLL, let’s call it container_in.cpp like this:

#include "container.h"
#include "container_impl.h"

template class __declspec(dllexport) Container<int>;

Now clients can already use the integer container, by including only container.h which does not contain the definitions!

More flexibility

But what if clients want to use a float container? With the current solution, they’ll get an error that the definition is not available. To get it working, the client has to include container_impl.h as well. But now, Container<int> will be instantiated twice, which leads to an error. The workaround is to define the instantiation as extern template, which means don’t generate code for this template even if the definition is available (for some reason or another, I just tried and it also works without the extern with Visual C++ 9). The finished file is:

#ifdef DLL_EXPORT // Set to true when you build the dll
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif

template <typename T>
class Container
{
// Container declaration
};

#ifndef IN_ // Note: For VC++, you can leave out the extern
extern template class API Container<int>;
#endif

The container_in.cpp file has to #define IN_ now. The client works like this:

#include "../shared_lib/templ.h"
#include "../shared_lib/templ.hpp"

#include <iostream>

int main (int, char**)
{
    Container<float> c1 (5); // Will be instantiated here

    c1.Set (3, 13.37f);
    std::cout < c1.Get (3) < std::endl;

    Container<int> c2 (4); // Will be linked in from the DLL

    c2.Set (1, 4711);
    std::cout < c2.Get (1) < std::endl;
}

That’s it!

Previous post
Next post

Recent posts

  • Effective meetings
    Posted on 2022-09-12
  • Advent 2021: Open source
    Posted on 2021-12-24
  • Advent 2021: Blender
    Posted on 2021-12-23
  • Advent 2021: Visual Studio Code
    Posted on 2021-12-22
  • Advent 2021: Thunderbird
    Posted on 2021-12-21
  • Older posts

Find me on the web

  • GitHub
  • GPU database
  • Projects

Follow me

Anteru NIV_Anteru
Contents © 2005-2023
Anteru
Imprint/Impressum
Privacy policy/Datenschutz
Made with Liara
Last updated February 03, 2019