See what's going on with flipcode!




This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

 

  Partial Template Specialization
  Submitted by



Template programming with C++ is always hell, compilers seem to enjoy making your life difficult when you try to use them, but just think about it in this way: they are merely defending themselves! , you are trying to make them doing all that nasty and repetitive work that you don’t want to do, and perhaps they have a point in being that annoying…

However we still have to keep on fighting them, and there are some very useful template features, such as partial template specialization, that may be required in some context and aren’t supported at all by most compilers, for instance lets consider a very simplistic container template such as this:

template <typename ElementType, int NUM_ELEMENTS
class SillyContainer
{

ElementType m_data[NUM_ELEMENTS];

public:

void setElement(int index, const ElementType& element) { m_data[index] = element; }

};



This seems quite straightforward, but right now think of using it with a complex data type, such an struct containing pointers (SillyVertexBuffer), that haven’t any kind of operator= or copy constructor overload, and you have to deep-copy… this simple container wouldn’t work… if you are using this container for that class you’ll have to create an partial specialization (just the type) of the template being able to deal with it properly:

struct SillyVertexBuffer
{
	typedef float Vertex[3];

int numVertices; Vertex* vertexPtr;

};

template <int NUM_ELEMENTS class SillyContainer<SillyVertexBuffer, NUM_ELEMENTS {

SillyVertexBuffer m_data[NUM_ELEMENTS];

public:

void setElement(int index, const SillyVertexBuffer& svb) { m_data[index].numVertices = svb.numVertices; memcpy(m_data[index].verticesPtr, svb.verticesPtr, \ svb.numVertices*sizeof(SillyVertexBuffer::Vertex)); }

};



But this wouldn’t work, because of the lack of support for partial template specialization. Fortunately there is a workaround, using template functions:

template <typename ElementType
static void deepCopy(ElementType& dst, const ElementType& src)
{
	dst = src;
}

template < static void deepCopy<SillyVertexBuffer(SillyVertexBuffer& dst, const SillyVertexBuffer& src) { dst.numVertices = src.numVertices; memcpy(dst.vertexPtr, src.vertexPtr, \ src.numVertices*sizeof(SillyVertexBuffer::Vertex)); }

template <typename ElementType, int NUM_ELEMENTS class SillyContainer {

ElementType m_data[NUM_ELEMENTS];

public:

void setElement(int index, const ElementType& element) { deepCopy(m_data[index], element); }

};



That recursive template instantiation policy should be powerful enough to deal with any other problem related with partial specialization. If you found any particular case where it isn’t please let me know.

Matt


The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

 

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.