Boost logo

Boost :

From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2001-12-14 12:03:19


Mat Marcus wrote:
> Aleksey> MSVC does compile this one :). I've uploaded the example
> Aleksey> file (derived_class_gen.cpp) to the MPL directory in the
> Aleksey> files section, if it's of any interest.
>
> MSVC 6 and 7b2 still refuse to compile this for me. Perhaps its
> because I'm using the 9/19 MPL?

MSVC 6.5 indeed rejected it, and after I've found a workaround, the
situation became exactly the opposite - the new code was compiling under VC
6.5, but rejected by 7.0b2. Working with a pair of MS compilers is even more
fun than with just one :). Anyway, I ifdef'ed the code that caused troubles,
and also uploaded a minor revision of the library that works with the latest
PREPROCESSOR library to the Files section
(http://groups.yahoo.com/group/boost/files/mpl/mpl-dec-01-01.zip, haven't
got time to check it in into CVS yet), so now everything should work.

> Also, I suggest that we add some
> author attribution to derived_class_gen.cpp.

Ouch, I thought I did it. Fixed.

> In particular, the Loki
> copyright notice should probably appear.

Done, but note that the code I posted as an example of "how I would write an
equivalent of Loki's GenScatterHierarchy using MPL" is _not_ derived from
the code in Andrei's book. It's a simplified version of "structure
generator" class template my colleague and I wrote some time ago here at
work; the class is basically used to generate a family of ordinary C++
structs (or "property classes", or "named tuples", depending on how you look
at them :) that can be freely assigned to each other basing on the
"compatibility" of their content, e.g.

    DEFINE_STRUCTURE_GEN_MEMBER(name);
    DEFINE_STRUCTURE_GEN_MEMBER(last_name);
    DEFINE_STRUCTURE_GEN_MEMBER(street);
    DEFINE_STRUCTURE_GEN_MEMBER(city);
    DEFINE_STRUCTURE_GEN_MEMBER(zip_code);

    // struct my_person
    // {
    // std::string m_name;
    // std::string m_street;
    // std::string m_city;
    // int m_zip_code;
    // };
    typedef structure_gen< boost::mpl::type_list<
          name<std::string>
        , street<std::string>
        , city<std::string>
        , zip_code<int>
> >::type my_person;
    
    // struct her_person
    // {
    // std::string m_name;
    // int m_zip_code;
    // };
    typedef structure_gen< boost::mpl::type_list<
          name<std::string>
        , zip_code<int>
> >::type her_person;

    int main()
    {
        my_person p1;
        her_person p2;

        p1.m_name = "Helena";
        p1.m_zip_code = 10001;
    
        p2 = p1; // ok
        assert(p2.m_name == p1.m_name);
        assert(p2.m_zip_code == p1.m_zip_code);
    
        // p1 = p2; // error
    }

where definitions of 'structure_gen' and DEFINE_STRUCTURE_GEN_MEMBER macro
are:

    namespace aux {

    // Dave Abrahams' technique: factoring out 'struct_t'
    // definition from 'struct_t_gen' (below) clears up the
    // generated type "signature"

    template<typename BaseStruct, typename T>
    struct struct_t : BaseStruct, T
    {
        struct_t() {}

        template<typename U> struct_t(U const& other)
            : BaseStruct(other)
            , T(static_cast<T const&>(other))
        {
        }

        template<typename U> struct_t& operator=(U const& other)
        {
            BaseStruct::operator=(other);
            T::operator=(static_cast<T const&>(other));
            return *this;
        }
    };

    struct struct_t_gen
    {
        template<typename BaseStruct, typename T>
        struct apply
        {
            // another Dave's technique: 'select_type' is used to avoid
            // a need to have/inherit from a dummy base class

            typedef typename boost::mpl::select_type<
                  boost::is_same<BaseStruct, boost::mpl::null_t>::value
                , T
                , struct_t<BaseStruct, T>
>::type type;
        };
    };

    } // namespace aux
            
    template<typename Memebers>
    struct structure_gen
    {
        typedef typename boost::mpl::accumulate<
              Memebers
            , boost::mpl::null_t
            , aux::struct_t_gen
>::type type;
    };

    #define DEFINE_STRUCTURE_GEN_MEMBER(name) \
    template<typename T> \
    struct name \
    { \
        typedef T value_type; \
        name(T x = T()) : m_##name(x) {} \
        T m_##name; \
    } \
    /**/

> Mat> * MPL needs documentation now. I believe some mpl naming
> Mat> conventions could be improved as well.
>
> Aleksey> Do you have any specific suggestions in mind (besides
> Aleksey> 'for_each' :)?
>
> The other idea is that the MAKE_F_XXX macros could be more suggestive
> once the right name for "function classes" is found.

I think the current names are ok, but I am always open to better
suggestions.

Aleksey


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk