0

Add the moment I play around with boost::mpl::* and try to extend the physical unit example. At the moment I have the following code:

A simple physical base dimension represented by an mpl::vector:

template < int Mass, int Length, int Time, int Temperature, int Angle, int Current >
    struct base_dimension
    {
        typedef typename mpl::vector_c< int, Mass, Length, Time, Temperature, Angle, Current >::type type;
    };

A scalar vector:

typedef base_dimension< 0, 0, 0, 0, 0, 0 >::type base_dimensionless_helper;

A simple type storing the base_dimension type:

template< class base_dimension >
    struct Dimension
    {
        typedef Dimension< base_dimension > type;
        typedef base_dimension              base_dim_type;
    };

A scalar Dimension:

typedef Dimension< base_dimensionless_helper > base_dimensionless;

Some simple helper:

template < class D1, int fac >
    struct mul_base_dim_fac_typeof
    {
        typedef typename base_dimension< fac, fac, fac, fac, fac, fac >::type fac_vec;
        typedef typename Detail::multiply_typeof_helper< typename D1, fac_vec >::type type;
    };


template < class Dim1, class Dim2 >
    struct add_dim_typeof_helper
    {
        typedef typename add_base_dim_typeof_helper< typename Dim1::base_dim_type, typename Dim2::base_dim_type >::type dim;

        typedef Dimension< dim > type;
    };

And finally a derived dimension. The used formula is: (D0 * E0) + (D1 * E1) +...+ (D5 * E5) ... ::type

template < class D0 = base_dimensionless, int E0 = 0,
       class D1 = base_dimensionless, int E1 = 0,
       class D2 = base_dimensionless, int E2 = 0,
       class D3 = base_dimensionless, int E3 = 0,
       class D4 = base_dimensionless, int E4 = 0,
       class D5 = base_dimensionless, int E5 = 0 >
struct derived_dimension
{
    typedef Dimension< typename mul_base_dim_fac_typeof< typename D0::base_dim_type, E0 >::type > d0_type;
    typedef Dimension< typename mul_base_dim_fac_typeof< typename D1::base_dim_type, E1 >::type > d1_type;
    typedef Dimension< typename mul_base_dim_fac_typeof< typename D2::base_dim_type, E2 >::type > d2_type;
    typedef Dimension< typename mul_base_dim_fac_typeof< typename D3::base_dim_type, E3 >::type > d3_type;
    typedef Dimension< typename mul_base_dim_fac_typeof< typename D4::base_dim_type, E4 >::type > d4_type;
    typedef Dimension< typename mul_base_dim_fac_typeof< typename D5::base_dim_type, E5 >::type > d5_type;

    typedef typename Detail::add_dim_typeof_helper< d0_type, d1_type >::type d0_d1_type;
    typedef typename Detail::add_dim_typeof_helper< d0_d1_type, d2_type >::type d0_d1_d2_type;
    typedef typename Detail::add_dim_typeof_helper< d0_d1_d2_type, d3_type >::type d0_d1_d2_d3_type;
    typedef typename Detail::add_dim_typeof_helper< d0_d1_d2_d3_type, d4_type >::type d0_d1_d2_d3_d4_type;
    typedef typename Detail::add_dim_typeof_helper< d0_d1_d2_d3_d4_type, d5_type >::type type;
};

Ok this does work as expected. But I want to beautify the calculation of the derived dimension because all these intermediate typedefs are ugly. My first idea was to push the input vectors into one vector (-> a vector of vectors) and to multiply them within one nice for_each loop but until now without success. So my question is:

Any hints how to beautify the calculation ?

Luc Touraille
  • 79,925
  • 15
  • 92
  • 137
Maik
  • 541
  • 4
  • 15

1 Answers1

0

You could start by defining an helper function, to clarify the multiplication:

template < typename D, int E >
struct multiply
{
    typedef Dimension< typename 
        mul_base_dim_fac_typeof< typename 
            D::base_dim_type, 
            E
        >::type
    > type;
};

You could also use algorithms such as transform and fold (well, you would rather need reduce, but it is not provided in MPL):

template < class D0 = base_dimensionless, int E0 = 0,
           class D1 = base_dimensionless, int E1 = 0,
           class D2 = base_dimensionless, int E2 = 0,
           class D3 = base_dimensionless, int E3 = 0,
           class D4 = base_dimensionless, int E4 = 0,
           class D5 = base_dimensionless, int E5 = 0 >
struct derived_dimension
{
    typedef mpl::vector<
        mpl::pair< D0, E0 >, mpl::pair< D1, E1 >,
        mpl::pair< D2, E2 >, mpl::pair< D3, E3 >,
        mpl::pair< D4, E4 >, mpl::pair< D5, E5 >
    > pairs;

    typedef typename
        mpl::transform< 
            pairs, 
            multiply< mpl::first< mpl::_1 >, mpl::second< mpl::_1 >;
        >::type products;

    typedef typename
        mpl::fold<
            products,
            base_dimensionless,
            add_dim_typeof_helper< mpl::_, mpl::_ >
        >::type type;
};

DISCLAIMER: I haven't tested this code at all, its aim is just to give you an idea of what can be done with MPL.

Alternatively, you could use the preprocessor to generate the consecutive typedefs, probably with the help of Boost.Preprocessor.

Luc Touraille
  • 79,925
  • 15
  • 92
  • 137