Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Small exercise with template metaprogramming

Reply
Thread Tools

Small exercise with template metaprogramming

 
 
mathieu
Guest
Posts: n/a
 
      03-29-2006
Hello there,

I am playing around with template metaprograming: I am trying to
redefines my own types. But I am facing a small issue, where I cannot
describe the whole implementation in one single class. Instead I have
to separate implementation for binary and ascii in two different
classes as I don't know how to use the traits technique for
constructors.

Any pointers very welcome !
Mathieu
Ps: My goal is collapse MyASCIITypes and MyTypes in one single
templated class.

Full source is:
#include <iostream> // cout
#include <sstream> // istringstream

typedef enum {
ASCII= 0,
BINARY
} Modes;

// Define my types
typedef enum {
Type1 = 1,
Type2,
Type3,
Type4,
} Types;

// Defines my value multiplicity
typedef enum {
VM1,
VM2,
VM3,
VM4,
VM5,
VM6,
VM8,
} VMTypes;

// Mapping from Enum type to a Mode
template<int T> struct EnumTypeToMode;
template<> struct EnumTypeToMode<Type1>
{ enum { Mode = ASCII }; };
template<> struct EnumTypeToMode<Type2>
{ enum { Mode = BINARY }; };
template<> struct EnumTypeToMode<Type3>
{ enum { Mode = BINARY }; };
template<> struct EnumTypeToMode<Type4>
{ enum { Mode = ASCII }; };

// Mapping from Enum type to a real type
template<int T> struct TypeEnumToType;
template<> struct TypeEnumToType<Type1>
{ typedef float Type; };
template<> struct TypeEnumToType<Type2>
{ typedef double Type; };
template<> struct TypeEnumToType<Type3>
{ typedef int Type; };
template<> struct TypeEnumToType<Type4>
{ typedef unsigned int Type; };


template<int T> struct ValueEnumToLength;
template<> struct ValueEnumToLength<VM1>
{ enum { Len = 1 }; };
template<> struct ValueEnumToLength<VM2>
{ enum { Len = 2 }; };
template<> struct ValueEnumToLength<VM3>
{ enum { Len = 3 }; };
template<> struct ValueEnumToLength<VM4>
{ enum { Len = 4 }; };
template<> struct ValueEnumToLength<VM5>
{ enum { Len = 5 }; };
template<> struct ValueEnumToLength<VM6>
{ enum { Len = 6 }; };
template<> struct ValueEnumToLength<VM8>
{ enum { Len = 8 }; };

// forward declaration
template<int T> class ModeImplementation;

// Definition of my type
template<int Type, int Size>
class MyTypes
{
public:
typename TypeEnumToType<Type>::Type
Data[ValueEnumToLength<Size>::Len];
int GetLength() const {
return ValueEnumToLength<Size>::Len;
}
void Print() const {
ModeImplementation< EnumTypeToMode<Type>::Mode >:rint(Data,
GetLength());
}
};

// Implementation for Mode=ASCII
template<> class ModeImplementation<ASCII>
{
public:
template <typename T>
static inline void Print(const T array[], const int len) {
std::cout << "ASCII:" << array[0]; // garantee to be >1
for(int i=1; i<len; ++i)
std::cout << "," << array[i];
std::cout << std::endl;
}
};
// Implementation for Mode=BINARY
template<> class ModeImplementation<BINARY>
{
public:
template <typename T>
static inline void Print(const T array[], const int len) {
std::cout << "BINARY:" << array[0];
for(int i=1; i<len; ++i)
std::cout << "," << array[i];
std::cout << std::endl;
}
};

template<int Type, int Size>
class MyASCIITypes : public MyTypes<Type,Size>
{
public:
MyASCIITypes(const char array[])
{
const int length = ValueEnumToLength<Size>::Len;
std::istringstream is(array);
int i = 0;
while( is >> this->Data[i++] );
assert( length == i-1 );
}
};

int main()
{
MyTypes<Type4,VM4> t_bin = { 1, 2, 3, 4 };
t_bin.Print();

MyASCIITypes<Type3,VM4> t_text = "1 2 3 4";
t_text.Print();

return 0;
}

 
Reply With Quote
 
 
 
 
mathieu
Guest
Posts: n/a
 
      04-02-2006
And to answer myself... I did not find a very elegant solution, but
still is fairly decent. Complete souce is (*). It would be nicer if
partial specialization would allow to define is for all ASCII type
instead of one at a time (in my case Type4 only is defined).

(*)
#include <iostream> // cout
#include <sstream>

typedef enum {
ASCII= 0,
BINARY
} Modes;

// Define my types
typedef enum {
Type1 = 1,
Type2,
Type3,
Type4,
} Types;

// Defines my value multiplicity
typedef enum {
VM1,
VM2,
VM3,
VM4,
VM5,
VM6,
VM8,
} VMTypes;

// Mapping from Enum type to a Mode
template<int T> struct EnumTypeToMode;
template<> struct EnumTypeToMode<Type1>
{ enum { Mode = ASCII }; };
template<> struct EnumTypeToMode<Type2>
{ enum { Mode = BINARY }; };
template<> struct EnumTypeToMode<Type3>
{ enum { Mode = BINARY }; };
template<> struct EnumTypeToMode<Type4>
{ enum { Mode = ASCII }; };

// Mapping from Enum type to a real type
template<int T> struct TypeEnumToType;
template<> struct TypeEnumToType<Type1>
{ typedef float Type; };
template<> struct TypeEnumToType<Type2>
{ typedef double Type; };
template<> struct TypeEnumToType<Type3>
{ typedef int Type; };
template<> struct TypeEnumToType<Type4>
{ typedef unsigned int Type; };


template<int T> struct ValueEnumToLength;
template<> struct ValueEnumToLength<VM1>
{ enum { Len = 1 }; };
template<> struct ValueEnumToLength<VM2>
{ enum { Len = 2 }; };
template<> struct ValueEnumToLength<VM3>
{ enum { Len = 3 }; };
template<> struct ValueEnumToLength<VM4>
{ enum { Len = 4 }; };
template<> struct ValueEnumToLength<VM5>
{ enum { Len = 5 }; };
template<> struct ValueEnumToLength<VM6>
{ enum { Len = 6 }; };
template<> struct ValueEnumToLength<VM8>
{ enum { Len = 8 }; };

// forward declaration
template<int T> class ModeImplementation;

// Definition of my type
template<int Type, int Size>
class MyTypes
{
public:
typename TypeEnumToType<Type>::Type
Data[ValueEnumToLength<Size>::Len];
int GetLength() const {
return ValueEnumToLength<Size>::Len;
}
void Print() const {
ModeImplementation< EnumTypeToMode<Type>::Mode >:rint(Data,
GetLength());
}
};

// Implementation for Mode=ASCII
template<> class ModeImplementation<ASCII>
{
public:
template <typename T>
static inline void Print(const T array[], const int len) {
std::cout << "ASCII:" << array[0]; // garantee to be >1
for(int i=1; i<len; ++i)
std::cout << "," << array[i];
std::cout << std::endl;
}
};
// Implementation for Mode=BINARY
template<> class ModeImplementation<BINARY>
{
public:
template <typename T>
static inline void Print(const T array[], const int len) {
std::cout << "BINARY:" << array[0];
for(int i=1; i<len; ++i)
std::cout << "," << array[i];
std::cout << std::endl;
}
};

template<int Size>
class MyTypes<Type4,Size>
{
public:
MyTypes(const char array[])
{
const int length = ValueEnumToLength<Size>::Len;
std::istringstream is(array);
int i = 0;
while( is >> this->Data[i++] );
assert( length == i-1 );
}
int GetLength() const {
return ValueEnumToLength<Size>::Len;
}
void Print() const {
ModeImplementation<ASCII>:rint(Data, GetLength());
}
private:
typename TypeEnumToType<Type4>::Type
Data[ValueEnumToLength<Size>::Len];
};


int main()
{
MyTypes<Type3,VM4> t_bin = { 1, 2, 3, 4 };
t_bin.Print();

MyTypes<Type4,VM4> t_text = "1 2 3 4";
t_text.Print();

return 0;
}

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[ANN] Article: An Exercise in Metaprogramming with Ruby rubyhacker@gmail.com Ruby 15 03-29-2006 12:05 AM
C++ Template Metaprogramming David Abrahams C++ 3 07-16-2004 09:53 AM
Giving proper credit to 'template metaprogramming' Sarah Thompson C++ 2 04-23-2004 07:06 PM
Template metaprogramming = interpretation Dave C++ 12 12-26-2003 12:12 PM
Sorting via template metaprogramming - critique requested Dave C++ 0 12-12-2003 08:48 PM



Advertisments