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).
Can you pls. help me?
#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;
}