Boost logo

Boost Users :

Subject: [Boost-users] [fusion 1.55.0] fusion::map avoid copy construction for elements
From: Frank Bergemann (fbergemann_at_[hidden])
Date: 2014-03-27 04:29:16


Hi,
[using gcc-4.7.2 on Red Hat Linux 6.2]
i have problems to avoid copy construction for fusion::map elements. See test program below. It shall pass a fusion::map as context along a call hierarchy with option to add elements (and in future maybe modify elements - if possible).
Either i use 
#define USE_RVALUE_REF 0
and have copy-constructions (strange especially for the at_key lookup for Data in exec2()!)
Or i use
#define USE_RVALUE_REF 1
and get a compilation problem for code to "retrieve Data..."
Can you pls. help me?
- thanks!
best regards,
Frank
--------------- main.cpp --------------------------
#include <iostream>
#include <string>
#include <utility>
#include <boost/fusion/container/map.hpp>
#include <boost/fusion/include/at_key.hpp>
#include <boost/fusion/algorithm.hpp>
using namespace boost;
#define USE_RVALUE_REF 0
#define NAMED_STRUCT(Name)                         \
    struct Name                             \
    {                                 \
        static constexpr char const * const name = #Name;    \
    }
namespace fields
{
    NAMED_STRUCT(Name);
    NAMED_STRUCT(Age);
    NAMED_STRUCT(Weight);
    NAMED_STRUCT(Foo);
    NAMED_STRUCT(Data);
}
struct Data
{
    int _x;
    Data(int x)
    : _x(x)
    { }
    Data (Data const & data)
    : _x(data._x)
    {
        std::cerr << "Data::copy c'tor invoked" << std::endl;
    }
};
std::ostream &
operator<<(std::ostream & out, Data const & data)
    {
        out << "{_x= " << data._x << "}";
        return out;
    }
typedef fusion::map<
        fusion::pair<fields::Name, std::string>
    ,    fusion::pair<fields::Age, int>
    ,    fusion::pair<fields::Weight, int>
#if USE_RVALUE_REF
    ,    fusion::pair<fields::Data, Data&&>
#else
,    fusion::pair<fields::Data, Data>
#endif
> Person;
struct logger
{
    template <typename Pair>
    void operator()(Pair const & data) const
    {
        std::cout << Pair::first_type::name << ":" << data.second << ",";
    }
};
template <typename Context>
void
exec2(Context & context)
{
    fusion::for_each(context, logger());
    std::cout << std::endl;
    // use intial stuff from main (Person)
    typename fusion::result_of::at_key<Context,fields::Name>::type const &
    name (fusion::at_key<fields::Name>(context));
    std::cout << "name = " << name << std::endl;
#if not USE_RVALUE_REF
    std::cerr << "retrieve Data..." << std::endl;
    // use extension from exec1 (extended context)
    typename fusion::result_of::at_key<Context,fields::Data>::type const &
    data (fusion::at_key<fields::Data>(context));
    std::cout << "data = " << data << std::endl;
    std::cerr << "...done" << std::endl;
#endif
}
template <typename Context>
void
exec1(Context & context)
{
    fusion::for_each(context, logger());
    std::cout << std::endl;
    typedef fusion::map<
        fusion::pair<fields::Foo, int>
    > Extension;
    Extension extension(0);
    typename fusion::joint_view<Context, Extension>
    contextExtended(context, extension);
    exec2(contextExtended);
}
int
main(int, char **)
{
    std::cerr << "construction..." << std::endl;
    Person person(std::string("Frank"), 46, 86, Data(1));
    std::cerr << "...done" << std::endl;
    std::cerr << "exec1..." << std::endl;
    exec1(person);
    std::cerr << "...done" << std::endl;
    return 0;
}

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