|
Boost Users : |
Subject: Re: [Boost-users] fusion struct adapt macro, construct the struct from a fusion vector
From: Nat Goodspeed (nat_at_[hidden])
Date: 2010-01-20 16:24:06
Joel de Guzman wrote:
> Or, if you can wait a bit, I do intend to write an intrusive version of
> the FUSION_ADAPT_STRUCT which also generates the struct along with
> the constructors and assignment to/from fusion sequences. I dunno,
> perhaps you can persuade a fusion guru to write the code (Christopher)? :-)
This isn't all of the above, but the attached worked for me as of Boost
1.35.0...
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/transform.hpp>
// only for testing
#include <iostream>
// BOOST_FUSION_BUILD_STRUCT() borrows its syntax from
// BOOST_FUSION_ADAPT_STRUCT(). The general idea is that you write the same
// code you'd have written for BOOST_FUSION_ADAPT_STRUCT(), but the _BUILD_
// variant actually declares the struct for you as well. The trouble with
// BOOST_FUSION_ADAPT_STRUCT's member syntax is that it's a PP sequence of
// tuples. BOOST_PP_SEQ_FOR_EACH() handles sequences of single tokens fine,
// but a sequence of tuples breaks it. An implementation based on
// BOOST_PP_SEQ_FOR_EACH() would require double parentheses, e.g.:
// BOOST_FUSION_BUILD_STRUCT(employee, ((std::string, name))((int, age)))
// But clearly BOOST_FUSION_ADAPT_STRUCT() manages to avoid that, so we borrow
// its implementation. Thanks to Paul Mensonides and Joel de Guzman!
#define BOOST_FUSION_BUILD_STRUCT(name, bseq) \
BOOST_FUSION_BUILD_STRUCT_I( \
name, BOOST_PP_CAT(BOOST_FUSION_BUILD_STRUCT_X bseq, 0)); \
BOOST_FUSION_ADAPT_STRUCT(name, bseq) \
/***/
#define BOOST_FUSION_BUILD_STRUCT_X(x, y) ((x, y)) BOOST_FUSION_BUILD_STRUCT_Y
#define BOOST_FUSION_BUILD_STRUCT_Y(x, y) ((x, y)) BOOST_FUSION_BUILD_STRUCT_X
#define BOOST_FUSION_BUILD_STRUCT_X0
#define BOOST_FUSION_BUILD_STRUCT_Y0
// BOOST_FUSION_BUILD_STRUCT_I generates the overarching structure and uses
// SEQ_FOR_EACH_I to generate the "linear" substructures.
// Thanks to Paul Mensonides for the PP macro help.
#define BOOST_FUSION_BUILD_STRUCT_I(name, seq) \
struct name \
{ \
name(BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(BOOST_FUSION_BUILD_STRUCT_P, ~, seq))): \
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(BOOST_FUSION_BUILD_STRUCT_MI, ~, seq)) \
{} \
BOOST_PP_SEQ_FOR_EACH_I(BOOST_FUSION_BUILD_STRUCT_C, ~, seq) \
} \
/***/
#define BOOST_FUSION_BUILD_STRUCT_P(r, ignore, xy) \
BOOST_PP_TUPLE_ELEM(2, 0, xy) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, xy), _) \
/***/
#define BOOST_FUSION_BUILD_STRUCT_MI(r, ignore, xy) \
BOOST_PP_TUPLE_ELEM(2, 1, xy)(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, xy), _)) \
/***/
#define BOOST_FUSION_BUILD_STRUCT_C(r, ignore, i, xy) \
BOOST_PP_TUPLE_ELEM(2, 0, xy) BOOST_PP_TUPLE_ELEM(2, 1, xy); \
/***/
// Example
BOOST_FUSION_BUILD_STRUCT(employee,
(std::string, name)
(int, age))
int main(int argc, char *argv[])
{
employee Jane("Jane", 37);
std::cout << "Name " << Jane.name << ", age " << Jane.age << '\n';
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