/*
* John Martin: john.p.martin@eudoramail.com
*
* This file demostrates the typeselect utility template. This file utilizes
* code derived from Andrei Alexandrescu's book: Modern C++ Design, Design Patterns
* and Generic Programming Applied published by Addison Wesley. His code is free
* to use and so is mine. Enjoy.
*
*/
#include <iostream>
using namespace std;
// used to terminate typelists
class null_type {};
// used to recursively create lists of types
template <class U, class V>
struct typelist
{
typedef U head_type;
typedef V tail_type;
};
// helper macros for managing typelists
#define TL_1(T1) typelist<T1, null_type>
#define TL_2(T1,T2) typelist<T1, TL_1(T2) >
#define TL_3(T1,T2,T3) typelist<T1, TL_2(T2,T3) >
#define TL_4(T1,T2,T3,T4) typelist<T1, TL_3(T2,T3,T4) >
// used to choose between two types at compile time
template <bool Expr, class U, class V>
struct select_type
{
typedef U result_type;
};
// specialization for false conditions
template <class U, class V>
struct select_type<false, U, V>
{
typedef V result_type;
};
// choose a type based on a specific size
template <unsigned int Size, class TList>
struct select_type_size;
template <unsigned int Size, class U, class V>
struct select_type_size<Size, typelist<U, V> >
{
typedef typename select_type
<
Size == sizeof(U),
U,
typename select_type_size<Size, V>::result_type
>::result_type result_type;
};
// specialization if a type is not found use null_type to generate a compile time error
template <unsigned int Size>
struct select_type_size<Size, null_type>
{
typedef null_type result_type;
};
// define a list of types
typedef TL_4(signed char, short int, int, long int) signed_ints;
typedef TL_4(unsigned char, unsigned short, unsigned int, unsigned long)
unsigned_ints;
// now when we port to different platforms we have guaranteed fixed size types
// or the compiler generates an error if we use an invalid type.
typedef select_type_size<1, signed_ints>::result_type int8_t;
typedef select_type_size<2, signed_ints>::result_type int16_t;
typedef select_type_size<4, signed_ints>::result_type int32_t;
typedef select_type_size<1, unsigned_ints>::result_type uint8_t;
typedef select_type_size<2, unsigned_ints>::result_type uint16_t;
typedef select_type_size<4, unsigned_ints>::result_type uint32_t;
// what select_type_size does is iterate through a list of types at compile
// time looking for a type of a specific size, when its found it sets
int main(int argc, char** argv)
{
cout << "sizeof(int8_t) == " << sizeof(int8_t) << endl;
cout << "sizeof(int16_t) == " << sizeof(int16_t) << endl;
cout << "sizeof(int32_t) == " << sizeof(int32_t) << endl;
cout << "sizeof(uint8_t) == " << sizeof(uint8_t) << endl;
cout << "sizeof(uint16_t) == " << sizeof(uint16_t) << endl;
cout << "sizeof(uint32_t) == " << sizeof(uint32_t) << endl;
return 0;
} |