Boost logo

Boost Users :

From: Andy Little (andy_at_[hidden])
Date: 2004-03-15 06:35:56


"Aleksey Gurtovoy" <agurtovoy_at_[hidden]> wrote in message
news:009d01c40a65$691f7360$6401a8c0_at_metacomm.com...
> Matt Calabrese wrote:
> > Okay, I decided before I continue with my other library, I'll fully
> > implement rational_c properly (and possibly fixed_c), however, doing
> > so without making the code horribly complex would require changes to
> > the current definitions of pretty much all of the operations (plus,
> > multiplies, etc. as well as the conditional operators).
> ^^^^^^^^^^^
> I suppose you meant "comparison", here and below.
>
> >
> > The problem is that those current functions take 5 parameters, making
> > specialization nearly impossible for the rational and fixed templates
> > as you'd have to account for when the 3rd, 4th, 5th, etc parameters
> > are not passed (and so the default integral 0 is used). That can't be
> > easily done (at least I don't see how) without having to specialize
> > each condition separately (one for 3 rational types, one for 4
> > rational types, etc ). Moreso, this applies to the conditional
> > operators as well, there is no easy way to account for using different
> > types in multiplies IE multiplying a rational and integral together,
> > or a fixed and rational, etc. Again, to account for these
> > possibilities you'd have to make an incredibly large amount of
> > specializations.

I have come up against the above problems.
My solution was to create a metafunction like so:

template<
 typename A,
 typename Op, // some type representing the op.
   //I actually use template<typename> class Op
   // with std::plus etc as the token
 typename B
>
struct binary_operation{
 typedef ... result_type; // works with result_of
};

notably compatible with mpl::plus (say);
(This is actually my standalone impl of mpl ops.
I dont use the extra params.
OTOH My impl is easy to replace with official version

namespace boost{namespace mpl{
 template<
 typename A,
 typename B
>
 struct plus<A,B> // unused params default aways
 {
  typedef typename binary_operation<
  A, std::plus,B
>::result_type type;
 };
}}

Actually definition for my rational_c op integral_c and vice versa is then:
(Assuming binary_operation<rational_c<..>,Op,Rational_c<..> > defined

 // mpl::integral_c support
    template<
        typename IntegerType1,
        IntegerType1 N1,
        IntegerType1 D1,
        template <typename> class Op,
        typename IntegerType2,
        IntegerType2 N2
>
    struct binary_operation<
        rational_c<IntegerType1,N1,D1>,
        Op,
        boost::mpl::integral_c<IntegerType2,N2>
>{
        typedef typename arithmetic_promote<
            IntegerType1,
            IntegerType2
>::type promoted_type;
        typedef typename binary_operation<
            rational_c<promoted_type,N1,D1>,
            Op,
            rational_c<promoted_type,N2,1>
>::result_type result_type;
    };

     template<
        typename IntegerType1,
        IntegerType1 N1,
        template <typename> class Op,
        typename IntegerType2,
        IntegerType2 N2,
        IntegerType2 D2
>
    struct binary_operation<
        boost::mpl::integral_c<IntegerType1,N1>,
        Op,
        rational_c<IntegerType2,N2,D2>
>{
        typedef typename meta::arithmetic_promote<
            IntegerType1,
            IntegerType2
>::type promoted_type;
        typedef typename binary_operation<
               rational_c<promoted_type,N1,1>,
               Op,
               rational_c<promoted_type,N2,D2>
>::result_type result_type;
    }

which cuts down the work some :-)

regards
Andy Little


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net