Small exercise with template metaprogramming

Discussion in 'C++' started by mathieu, Mar 29, 2006.

  1. mathieu

    mathieu Guest

    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;
    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;
    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;
    }
     
    mathieu, Mar 29, 2006
    #1
    1. Advertising

  2. mathieu

    mathieu Guest

    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;
    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;
    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;
    }
     
    mathieu, Apr 2, 2006
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jonathan Turkanis

    Small C++ exercise

    Jonathan Turkanis, Mar 6, 2005, in forum: C++
    Replies:
    8
    Views:
    693
    beerrock
    Mar 9, 2005
  2. J Peterman
    Replies:
    8
    Views:
    427
    Mark McIntyre
    Oct 14, 2003
  3. Mike S
    Replies:
    8
    Views:
    422
    Netocrat
    May 21, 2006
  4. ros

    small java exercise

    ros, Apr 3, 2007, in forum: Java
    Replies:
    35
    Views:
    1,362
    Chris Smith
    May 18, 2007
  5. Replies:
    15
    Views:
    195
    James Edward Gray II
    Mar 29, 2006
Loading...

Share This Page