Boost logo

Boost Users :

From: Ovanes Markarian (om_boost_at_[hidden])
Date: 2007-01-10 15:29:44


Hi!

you could use an mpl::pair type to produce a static mapping of int value to type:

mpl::pair<mpl::int_<0>, int>

This is a little bit ugly, to write such a big construct, so you can write the following construct

template<int N, class T>
struct pair_c : mpl::pair<mpl::int_<N>, T>
{};

Actually pair_c could be your DataField struct, so you can add the T instance to it:

template<int N, class T>
struct pair_c : mpl::pair<mpl::int_<N>, T>
{
   T dataField;
};

Now you can define a vector of pair types as follows:
mpl::vector<pair_c<0, int>, pair_c<1, int>, pair_c<2, int> > my_vector;

we use in this sample pair_c to make any type unique, dependent on the position in the vector.

The next step would be to define the class with linear inheritance:

template<class Seq>
struct linear_inherited :
        boost::mpl::inherit_linearly
        <
                Seq
        , boost::mpl::inherit<boost::mpl::_1, boost::mpl::_2>
>::type
{};

But now you would need the access function. I suggest to integrate this function as a
linear_inherited member:

template<class Seq>
struct linear_inherited :
        boost::mpl::inherit_linearly
        <
                Seq
        , boost::mpl::inherit<boost::mpl::_1, boost::mpl::_2>
>::type
{
        template<long N>
        typename boost::mpl::at_c<Seq, N>::type::second& nth_field()
        {
                typedef typename boost::mpl::at_c<Seq, N>::type* ptr_type;
                ptr_type ptr = static_cast<ptr_type>(this);
                return ptr->dataField;
        }

};

When this function is a member you save some effor on passing the sequence type to its
specialization, otherwise it will not know which type is meant.

Let me explain this function:

mpl has the at metafunction, which can access the Nth element of a static vector. Here this
function is used to calculate the result_type (in our case it is always int, but we want to be
generic ;), so you can make pair_c<0, double>, pair_c<1, SomeStruct> etc.). The at metafunction
returns the type which was in the vector at this position, in our case this type is pair_c. Now we
need to access the field type T. mpl::pair is defined as
template <class X, class Y>
struct pair
{
   typedef X first;
   typedef Y second;
};

so, the type of our datafield in pair_c is of type second. Therefore the function nth_field
returns reference to second.

In the function itself we use the static_cast operator to calculate the offset to our datafield
within the class. And then we return the the field contained there.

Below is the full listing I used to test and compile the scenario:

linear_inh_test.h
---------- START -------------------

#ifndef __OM_LINEAR_INHERITANCE_TEST_H__
#define __OM_LINEAR_INHERITANCE_TEST_H__

#include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/pair.hpp>
#include <boost/mpl/lambda.hpp>
#include <boost/mpl/inherit.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/inherit_linearly.hpp>

template<int N, class T>
struct pair_c : boost::mpl::pair<boost::mpl::int_<N>, T>
{
        T dataField;
};

template<class Seq>
struct linear_inherited :
        boost::mpl::inherit_linearly
        <
                Seq
        , boost::mpl::inherit<boost::mpl::_1, boost::mpl::_2>
>::type
{
        template<long N>
        typename boost::mpl::at_c<Seq, N>::type::second& nth_field()
        {
                typedef typename boost::mpl::at_c<Seq, N>::type* ptr_type;
                ptr_type ptr = static_cast<ptr_type>(this);
                return ptr->dataField;
        }

};

#endif

__________ END ___________________

main.cpp
---------- START -------------------

#include "linear_inh_test.h"

#include <cassert>
#include <boost/mpl/vector.hpp>

int main()
{
        using namespace boost;
        typedef mpl::vector<pair_c<0, int>, pair_c<1, int>, pair_c<2, int> > my_vector;

        linear_inherited<my_vector> test_instance;

        int& ref0 = test_instance.nth_field<0>();
        ref0 = 0;

        int& ref1 = test_instance.nth_field<1>();
        ref1 = 1;

        int& ref2 = test_instance.nth_field<2>();
        ref2 = 2;

        assert(
                        test_instance.nth_field<0>()
                  != test_instance.nth_field<1>()
                  != test_instance.nth_field<2>()
                  );

        return 0;
}

__________ END ___________________

With Kind Regards,

Ovanes Markarian

On Tue, January 9, 2007 21:51, Khalil Shalish wrote:
> Hello,
>
> I created the following composite class using mpl::inherit_linearly:
>
> template <class T>
> struct DataField {
> T data;
> }
>
> typedef mpl::inherit_linearly<
> mpl::vector< int, int, int>
> mpl::inherit< DataField<_2>, _1 >
>> Int3Composite;
>
> Int3Composite int3comp;
>
> Since the type of each data field is an int, I cannot use the type of the field to access the
data in the field.
>
> Q: Is there a way to write a template (call it get_field) to access the data using numeric
position in the type sequence. Something like this:
>
> int field_0 = get_field<0>(in3comp); //This returns the first int data field. int field_1 =
get_field<1>(int3comp);
>
> I am very new to C++ template programming and any help on this will be very much appreciated.
>
> Thank you,
> Khalil Shalish
> kshalish_at_[hidden]
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>

With Kind Regards,

Ovanes


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