Help | Site Map
Connecting Tech Pros Worldwide
 
 
LinkBack Thread Tools
  #1  
Old March 29th, 2006, 03:05 AM
mathieu
Guest
 
Posts: n/a
Default Small exercise with template metaprogramming

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 >::Print(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;
}

  #2  
Old April 2nd, 2006, 05:25 AM
mathieu
Guest
 
Posts: n/a
Default Re: Small exercise with template metaprogramming

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 >::Print(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>::Print(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;
}

 

Bookmarks


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
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 Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over network members.
Post your question now . . .
It's fast and it's free

Popular Articles