Anteru's blog
  • Consulting
  • Research
    • Assisted environment probe placement
    • Assisted texture assignment
    • 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
    • Subpixel Reconstruction Antialiasing
    • Tiled light trees
  • About
  • Archive

C++ tricks, #6: Explicit template instantiation

November 19, 2008
  • Programming
approximately 5 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

  • Five years of GPU DB
    Posted on 2020-09-27
  • Enabling SSL in your local network
    Posted on 2020-05-17
  • Goodbye, Bitbucket!
    Posted on 2020-03-19
  • QEMU, KVM and trim
    Posted on 2020-01-26
  • Fixing network after Ubuntu 19.04 to 19.10 upgrade
    Posted on 2019-10-26
  • Older posts

Find me on the web

  • GitHub
  • GPU database
  • Projects

Follow me

NIV_Anteru

Contents © 2005-2021 | Anteru | Imprint/Impressum | Privacy policy/Datenschutz