Boost Fusion User Extension

BoostFusion is arranged so that the user can extend it to provide their own objects which can be indexed either sequentially or by keyword. An example of this is given in the documentation. What follows is some of the code for this. The full code can be found in the BoostLibraries distribution. This is one way to build CppHeterogeneousContainers. -- JohnFletcher

 namespace example
 {
    struct example_struct
    {
        std::string name;
        int age;
        example_struct(const std::string& n,int a)
          : name(n), age(a) 
        {}
    };
 }

This can be accessed as follows:

 int main()
 {
    example::example_struct bert("bert", 99);
    using namespace boost::fusion;

BOOST_MPL_ASSERT((traits::is_associative<example::example_struct>)); BOOST_MPL_ASSERT((traits::is_random_access<example::example_struct>)); BOOST_MPL_ASSERT((traits::is_sequence<example::example_struct>));

BOOST_TEST(deref(begin(bert)) == "bert"); BOOST_TEST(*next(begin(bert)) == 99); BOOST_TEST(*prior(end(bert)) == 99); BOOST_TEST(*advance_c<1>(begin(bert)) == 99); BOOST_TEST(*advance_c<-1>(end(bert)) == 99); BOOST_TEST(distance(begin(bert), end(bert)) == 2);

typedef result_of::begin<example::example_struct>::type first; typedef result_of::next<first>::type second; BOOST_MPL_ASSERT((boost::is_same<result_of::value_of<first>::type, std::string>)); BOOST_MPL_ASSERT((boost::is_same<result_of::value_of<second>::type, int>));

BOOST_TEST(begin(bert) != end(bert)); BOOST_TEST(advance_c<2>(begin(bert)) == end(const_cast<const example::example_struct&>(bert)));

BOOST_TEST(at_c<0>(bert) == "bert"); BOOST_TEST(at_c<1>(bert) == 99);

BOOST_TEST(at_key<fields::name>(bert) == "bert"); BOOST_TEST(at_key<fields::age>(bert) == 99);

BOOST_TEST(has_key<fields::name>(bert)); BOOST_TEST(has_key<fields::age>(bert)); BOOST_TEST(!has_key<int>(bert));

BOOST_MPL_ASSERT((boost::is_same<result_of::value_at_c<example::example_struct, 0>::type, std::string>)); BOOST_MPL_ASSERT((boost::is_same<result_of::value_at_c<example::example_struct, 1>::type, int>));

BOOST_MPL_ASSERT((boost::is_same<result_of::value_at_key<example::example_struct, fields::name>::type, std::string>)); BOOST_MPL_ASSERT((boost::is_same<result_of::value_at_key<example::example_struct, fields::age>::type, int>));

BOOST_TEST(size(bert) == 2);

return boost::report_errors(); }

There is a set of tags set up as follows.

 namespace example
 {
    struct example_sequence_tag;    
 }

namespace boost { namespace fusion {

namespace traits {

template<> struct tag_of<example::example_struct> { typedef example::example_sequence_tag type; };

}}}

The tags are defined like this:

 namespace fields
 {
    struct name;
    struct age;
 }

namespace example { struct example_sequence_tag; }

namespace boost { namespace fusion {

namespace extension { template<typename Tag> struct at_key_impl;

template<> struct at_key_impl<example::example_sequence_tag> { template<typename Sequence, typename Key> struct apply;

template<typename Sequence> struct apply<Sequence, fields::name> { typedef typename mpl::if_< is_const<Sequence>, std::string const&, std::string&>::type type;

static type call(Sequence& seq) { return seq.name; }; };

template<typename Sequence> struct apply<Sequence, fields::age> { typedef typename mpl::if_< is_const<Sequence>, int const&, int&>::type type;

static type call(Sequence& seq) { return seq.age; }; }; }; } }}


CategoryBoost CategoryCpp CategoryCppTemplates CategoryContainer

EditText of this page (last edited January 26, 2014) or FindPage with title or text search