
March 29th, 2006, 03:05 AM
|
|
|
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;
}
|

April 2nd, 2006, 05:25 AM
|
|
|
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;
}
|
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|
|
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.
|