Template specialization for a group of types

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Marc Schellens

    Template specialization for a group of types

    I posted a similar question some time ago, but didn't get an
    satisfying answer.

    Lets say I have a template and five integer and two floating
    types.

    template <typename T> class A
    {
    A() {}
    ~A() {}

    public:
    void B( T);
    };

    // for all int
    template <typename T> void B( T)
    {
    // do something with int (char, unsigned int ...)
    }


    template<> void B( float)
    {
    // do something with float
    }
    template<> void B( double)
    {
    // do something with double where the code looks the same as for float
    }

    How to avoid to replicate the code for float and double?
    Or is it not possible?

    Thanks,
    marc

  • Patrick Kowalzick

    #2
    Re: Template specialization for a group of types

    Hi Marc,

    I just wanted to post the same question :-).

    What I do: I use macros for that purpose, but I do not like it :-(. Please
    see the code below:

    So I would be happy to get a nicer solution as well.

    Regards,
    Patrick


    // ***** CODE *****

    struct A_1 {};
    struct A_2 {};
    struct B_1 {};
    struct B_2 {};

    // my class bar
    template <typename> class bar;

    // first GROUP of specializations of bar
    #define create_class_A_ bar(CA) \
    template <> class bar<CA> \
    { \
    typedef CA used_type; \
    };

    // class definitions Group A
    create_class_A_ bar(A_1);
    create_class_A_ bar(A_2);

    // second GROUP of specializations of bar
    #define create_class_B_ bar(CB) \
    template <> class bar<CB> \
    { \
    typedef CB used_type; \
    };

    // class definitions Group A
    create_class_B_ bar(B_1);
    create_class_B_ bar(B_2);

    // some usage
    int main()
    {
    bar<A_1>;
    bar<A_2>;
    bar<B_1>;
    bar<B_2>;

    return 0;
    }


    Comment

    • tom_usenet

      #3
      Re: Template specialization for a group of types

      On Thu, 20 Nov 2003 14:25:22 +0900, Marc Schellens
      <m_schellens@ho tmail.com> wrote:
      [color=blue]
      >I posted a similar question some time ago, but didn't get an
      >satisfying answer.
      >
      >Lets say I have a template and five integer and two floating
      >types.
      >
      >template <typename T> class A
      >{
      >A() {}
      >~A() {}
      >
      >public:
      >void B( T);
      >};
      >
      >// for all int
      >template <typename T> void B( T)
      >{
      >// do something with int (char, unsigned int ...)
      >}
      >
      >
      >template<> void B( float)
      >{
      >// do something with float
      >}
      >template<> void B( double)
      >{
      >// do something with double where the code looks the same as for float
      >}
      >
      >How to avoid to replicate the code for float and double?
      >Or is it not possible?[/color]

      It is possible:

      /* If you can't use boost
      template <class T>
      struct is_integral
      {
      static bool const value = false;
      };

      template<> struct is_integral<int >{static bool const value = true;};
      template<> struct is_integral<uns igned>{static bool const value =
      true;};
      template<> struct is_integral<sho rt>{static bool const value = true;};
      template<> struct is_integral<uns igned short>{static bool const value
      = true;};
      template<> struct is_integral<cha r>{static bool const value = true;};
      template<> struct is_integral<uns igned char>{static bool const value =
      true;};
      template<> struct is_integral<sig ned char>{static bool const value =
      true;};
      template<> struct is_integral<lon g>{static bool const value = true;};
      template<> struct is_integral<uns igned long>{static bool const value =
      true;};

      //need const/volatile versions, etc. too!
      //what about bool?
      */
      // The boost version:
      #include <boost/type_traits.hpp >
      using boost::is_integ ral;

      template <typename T> class A
      {
      public:
      A() {}
      ~A() {}
      void B(T);
      };

      #include <iostream>

      template <bool B>
      struct B_impl
      {
      template <class T>
      static void impl(T t)
      {
      std::cout << "Integer version\n";
      }
      };
      template <>
      struct B_impl<false>
      {
      template <class T>
      static void impl(T t)
      {
      std::cout << "Float version\n";
      }
      };
      // for all int
      template <typename T> void A<T>::B(T t)
      {
      B_impl<is_integ ral<T>::value>: :impl(t);
      }

      int main()
      {
      A<short> a;
      a.B(5);

      A<double> b;
      b.B(7.5);
      }

      Tom

      Comment

      • Rob Williscroft

        #4
        Re: Template specialization for a group of types

        Marc Schellens wrote in news:3FBC5042.2 020806@hotmail. com:
        [color=blue]
        > I posted a similar question some time ago, but didn't get an
        > satisfying answer.
        >
        > Lets say I have a template and five integer and two floating
        > types.
        >
        > template <typename T> class A
        > {
        > A() {}
        > ~A() {}
        >
        > public:
        > void B( T);
        > };
        >
        > // for all int
        > template <typename T> void B( T)
        > {
        > // do something with int (char, unsigned int ...)
        > }
        >
        >
        > template<> void B( float)
        > {
        > // do something with float
        > }
        > template<> void B( double)
        > {
        > // do something with double where the code looks the same as for float
        > }
        >
        > How to avoid to replicate the code for float and double?
        > Or is it not possible?
        >[/color]

        An alternative is a simple refactor:

        template < typename T> A< T >::B( T arg )
        {
        // int version.
        }

        /* New (?private?) member
        template < typename T> A< T >::B_float( T arg )
        {
        // int version.
        }

        template <> inline A< float >::B( float arg )
        {
        B_float( arg );
        }

        template <> inline A< double >::B( double arg )
        {
        B_float( arg );
        }

        If you like typing (or you *need* to generalize),

        #include <iostream>
        #include <ostream>
        #include <limits>

        #if 0 /* boost is preferable if you have it */
        #include "boost/mpl/if.hpp"
        using boost::mpl::if_ c;
        #else
        template < bool True, typename TrueT, typename FalseT >
        struct if_c
        {
        typedef TrueT type;
        };
        template < typename TrueT, typename FalseT >
        struct if_c< false, TrueT, FalseT >
        {
        typedef FalseT type;
        };
        #endif

        template < typename T, typename Arg, void (T::*F)( Arg ) >
        struct member_ref_1
        {
        static void apply( T *that, Arg arg )
        {
        (that->*F)( arg );
        }
        };


        template < typename T > struct A
        {
        void B_int( T arg ) { std::cerr << "int\n"; }
        void B_float( T arg ) { std::cerr << "float\n"; }

        void B( T arg )
        {
        typedef
        if_c<
        std::numeric_li mits< T >::is_integer ,
        member_ref_1< A< T >, T, &A< T >::B_int >,
        member_ref_1< A< T >, T, &A< T >::B_float >[color=blue]
        >[/color]
        ::type type
        ;
        type::apply( this, arg );
        }
        };

        int main()
        {
        A< int > aint;
        aint.B( 0 );

        A< double > adouble;
        adouble.B( 0.0 );
        }

        Rob.
        --

        Comment

        • Chris Theis

          #5
          Re: Template specialization for a group of types


          "Patrick Kowalzick" <Patrick.Kowalz ick@cern.ch> wrote in message
          news:bphujb$ri3 $1@sunnews.cern .ch...[color=blue]
          > Hi Marc,
          >
          > I just wanted to post the same question :-).
          >
          > What I do: I use macros for that purpose, but I do not like it :-(. Please
          > see the code below:
          >
          > So I would be happy to get a nicer solution as well.
          >
          > Regards,
          > Patrick
          >
          >
          > // ***** CODE *****
          >
          > struct A_1 {};
          > struct A_2 {};
          > struct B_1 {};
          > struct B_2 {};
          >
          > // my class bar
          > template <typename> class bar;
          >
          > // first GROUP of specializations of bar
          > #define create_class_A_ bar(CA) \
          > template <> class bar<CA> \
          > { \
          > typedef CA used_type; \
          > };
          >
          > // class definitions Group A
          > create_class_A_ bar(A_1);
          > create_class_A_ bar(A_2);
          >
          > // second GROUP of specializations of bar
          > #define create_class_B_ bar(CB) \
          > template <> class bar<CB> \
          > { \
          > typedef CB used_type; \
          > };
          >
          > // class definitions Group A
          > create_class_B_ bar(B_1);
          > create_class_B_ bar(B_2);
          >
          > // some usage
          > int main()
          > {
          > bar<A_1>;
          > bar<A_2>;
          > bar<B_1>;
          > bar<B_2>;
          >
          > return 0;
          > }[/color]


          One possible solution would be the usage of type lists although, as
          discussed with Patrick, IMHO would be simply too much overhead for such a
          problem. The standard stream library has the same problem to cope with
          (overloading of op << for all the different POD types) and there you see
          that it's done "by hand". In lack of better ideas I'd personally stick with
          the macros. Sure, the statement "macros are evil" is more or less true but
          there are exceptions.

          Regards
          Chris


          Comment

          Working...