Using template specialization in C++
We all know that C++ templates can be used to write generic code, e.g.
template <typename T>
class Array { … };
Then we can use the same template to generate code for different template parameters. This is called instantiation of the template. e.g.
Array<int> x;
Array<string> y;
However, sometimes we don't want to use the same definition for certain template parameters. For example, the generic definition for Array<bool> might not be as efficient as we want. We can write a specialized implementation for Array<bool> that uses only 1 bit for each element in the array. Such is called specialization of the template.
C++ supports specialization by the following syntax:
template <> // empty template parameter list!
class Array<bool> { … };
Here's the complete example. In this program, we present a generic definition for a template class Array, then we present a specialized definition for the case when the template parameter is bool.
// This example shows how to supply a specialized implementation when
// instantiating C++ template class.
// This code is SIMPLIFIED for illustration purpose, and should NOT be used
// unmodified in production code!!!
// (c) Zhanyong Wan
// 3/17/2004
#include <iostream>
// The generic definition for the Array template class.
template <typename T>
class Array
{
private:
T * elements;
int size;
public:
Array( int aSize )
: size( aSize )
{
// size validity checking code omitted...
elements = new T[ aSize ];
// (elements != NULL) test omitted...
}
virtual ~Array()
{
delete[] elements;
}
void Set( int idx, const T& value )
{
// array-bound checking code omitted...
elements[ idx ] = value;
}
T& Get( int idx ) const
{
// array-bound checking code omitted...
return elements[ idx ];
}
};
typedef unsigned char byte;
// An specialized implementation for Array< bool > that optimizes for space
// by representing a bool element with a single bit.
// In C++, a template with an empty parameter list is the syntax for
// specialization. IMHO, keyword overloading is abused in C++.
template <>
class Array< bool >
{
private:
byte * buffer;
int size;
const static int BitsPerByte = 8;
public:
Array( int aSize )
{
// size validity checking code omitted...
buffer = new byte[ aSize/BitsPerByte + 1 ];
// (buffer != NULL) test omitted...
}
virtual ~Array()
{
delete[] buffer;
}
// The specialized class is NOT obliged to have the same set of methods
// as the generic class!
void Set( int idx, bool value )
// Note that we change the prototype of the Set() method here for better
// performance. As a result, it does not match the prototype of the
// Set() method in the template Array class. This is OK, as C++ doesn't
// impose any relationship between a template class and its specialization.
{
// array-bound checking code omitted...
const int byteIdx = idx/BitsPerByte;
const int bitIdx = idx - byteIdx*BitsPerByte;
const byte bitMask = 1 << bitIdx;
if ( value )
{
buffer[ byteIdx ] |= bitMask;
}
else
{
buffer[ byteIdx ] &= ~bitMask;
}
}
bool Get( int idx ) const
{
// array-bound checking code omitted...
const int byteIdx = idx/BitsPerByte;
const int bitIdx = idx - byteIdx*BitsPerByte;
const byte bitMask = 1 << bitIdx;
return ( buffer[ byteIdx ] & bitMask ) != 0;
}
};
int main()
{
const int size = 6;
Array< int > intArray ( size );
Array< bool > boolArray( size );
for ( int i = 0; i < size; i++ )
{
intArray.Set( i, i );
boolArray.Set( i, (i % 2) == 1 );
}
for ( i = 0; i < size; i++ )
{
std::cout << intArray.Get( i )
<< "\t"
<< boolArray.Get( i )
<< "\r\n";
}
return 0;
}
Comments
- Anonymous
July 25, 2004
dianying xia zai:http://www.kamun.com/
movie down:http://movie.kamun.com/
mp3 xia zai:http://music.kamun.com/
engage:http://club.kamun.com/