Using a boost::fusion::map in boost::spirit::karma

Posted by user1097105 on Stack Overflow See other posts from Stack Overflow or by user1097105
Published on 2012-11-14T22:57:22Z Indexed on 2012/11/14 23:00 UTC
Read the original article Hit count: 329

Filed under:
|
|

I am using boost spirit to parse some text files into a data structure and now I am beginning to generate text from this data structure (using spirit karma).

One attempt at a data structure is a boost::fusion::map (as suggested in an answer to this question). But although I can use boost::spirit::qi::parse() and get data in it easily, when I tried to generate text from it using karma, I failed.

Below is my attempt (look especially at the "map_data" type). After some reading and playing around with other fusion types, I found boost::fusion::vector and BOOST_FUSION_DEFINE_ASSOC_STRUCT. I succeeded to generate output with both of them, but they don't seem ideal: in vector you cannot access a member using a name (it is like a tuple) -- and in the other solution, I don't think I need both ways (member name and key type) to access the members.

#include <iostream>
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/fusion/include/map.hpp>
#include <boost/fusion/include/make_map.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/transform.hpp>

struct sb_key;
struct id_key;

using boost::fusion::pair;

typedef boost::fusion::map
  < pair<sb_key, int>
  , pair<id_key, unsigned long>
  > map_data;

typedef boost::fusion::vector < int, unsigned long > vector_data;

#include <boost/fusion/include/define_assoc_struct.hpp>
BOOST_FUSION_DEFINE_ASSOC_STRUCT(
    (), assocstruct_data,
    (int, a, sb_key)
    (unsigned long, b, id_key))

namespace karma =  boost::spirit::karma;

template <typename X>
std::string to_string ( const X& data )
{
  std::string generated;
  std::back_insert_iterator<std::string> sink(generated);
  karma::generate_delimited ( sink, karma::int_ << karma::ulong_, karma::space, data );
  return generated;
}

int main()
{
  map_data d1(boost::fusion::make_map<sb_key, id_key>(234, 35314988526ul));
  vector_data d2(boost::fusion::make_vector(234, 35314988526ul));
  assocstruct_data d3(234,35314988526ul);

  std::cout << "map_data as_vector: " << boost::fusion::as_vector(d1) << std::endl;
  //std::cout << "map_data to_string: " << to_string(d1) << std::endl; //*FAIL No 1*
  std::cout << "at_key (sb_key): " << boost::fusion::at_key<sb_key>(d1) << boost::fusion::at_c<0>(d1) << std::endl << std::endl;

  std::cout << "vector_data: " << d2 << std::endl;
  std::cout << "vector_data to_string: " << to_string(d2) << std::endl << std::endl;

  std::cout << "assoc_struct as_vector: " << boost::fusion::as_vector(d3) << std::endl;
  std::cout << "assoc_struct to_string: " << to_string(d3) << std::endl;
  std::cout << "at_key (sb_key): " << boost::fusion::at_key<sb_key>(d3) << d3.a << boost::fusion::at_c<0>(d3) << std::endl;

  return 0;
}

Including the commented line gives lots of pages of compilation errors, among which notably something like: no known conversion for argument 1 from ‘boost::fusion::pair’ to ‘double’ no known conversion for argument 1 from ‘boost::fusion::pair’ to ‘float’

Might it be that to_string needs the values of the map_data, and not the pairs? Though I am not good with templates, I tried to get a vector from a map using transform in the following way

template <typename P>
struct take_second
{
  typename P::second_type operator() (P p)
  {
    return p.second;
  }
};
// ... inside main()
pair <char, int> ff(32);
std::cout << "take_second (expect 32): "
  << take_second<pair<char,int>>()(ff) << std::endl;
std::cout << "transform map_data and to_string: "
  << to_string(boost::fusion::transform(d1, take_second<>())); //*FAIL No 2*

But I don't know what types am I supposed to give when instantiating take_second and anyway I think there must be an easier way to get (iterate over) the values of a map (is there?)

If you answer this question, please also give your opinion on whether using an ASSOC_STRUCT or a map is better.

© Stack Overflow or respective owner

Related posts about c++

Related posts about boost-spirit