1

I need to map values to a std::string ( with the following map, and BOOST_FUSION_ADAPT_STRUCT )

    std::map< TYPEX, std::string> author2name;
    struct Emp
   {
     std::string name;
     TYPEX author;
   };

With the following code i want to generate my output:

karma::rule< it, std::string()> quote = '"' >> karma::string >> '"';
karma::rule< it, Emp> emp = karma::delimit('\t')[ quite << quite[ author2name[ karma::_1] ]];

Emp x;
karma::generate( std::ostream_iterator<char>(std::cout), emp, x);

But it doesn't compile.

And is there a way that i could write a header like this:

karma::rule< it, std::vector<std::string>()> header = karma::delimit('\t')[ % quote];
karma::rule< it, Emp> emp = header >> karma::eol >> karma::delimit('\t')[ quite << quite[ author2name[ karma::_1] ]];

karma::generate( std::ostream_iterator<char>(std::cout), {"A", "B", "C"},emp, x);
Roby
  • 2,011
  • 4
  • 28
  • 55

1 Answers1

3

There is a number of small paper-cuts that killed you there :)

Working example:

Live On Coliru

#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <map>

namespace karma = boost::spirit::karma;
namespace phx   = boost::phoenix;

enum TYPEX { AUTHOR1, AUTHOR2, AUTHOR3, AUTHOR4 };

std::map<TYPEX, std::string> author2name;
struct Emp {
    std::string name;
    TYPEX author;
};

BOOST_FUSION_ADAPT_STRUCT(Emp, name, author) // boost 1_59
//BOOST_FUSION_ADAPT_STRUCT(Emp, (std::string, name)(std::string, author)) // older boost

int main() {
    using it = boost::spirit::ostream_iterator;

    karma::rule<it, std::string()> quote;
    karma::rule<it, TYPEX()> author;
    karma::rule<it, Emp()> emp;

    {
        using namespace karma;
        quote  %= '"' << string << '"';
        author  = quote [ _1 = phx::ref(author2name)[ _val ] ];
        emp    %= delimit('\t')[ quote << author ];
    }

    Emp x { "one", AUTHOR2 };
    author2name[AUTHOR2] = "TWO!";
    std::cout << karma::format(emp, x);
}

Prints:

"one"   "TWO!"  

The things that caused trouble:

  • suggest to use boost::spirit::ostream_iterator and karma::format for more user-friendly API
  • Add the missing parentheses on emp:

    karma::rule<it, Emp()> emp;
    

    NOTE: very recent boost (1_59 IIRC) doesn't not require these anymore. Which is why I found out only on Coliru

  • Here:

    quote[ author2name[ karma::_1] ]
    

    you index [] into a std::map using ... qi::_1. That can't compile. What you wanted was to invoke the Phoenix lazy expression template of operator[]. You have to include the Phoenix header and force author2name to be a Phoenix reference actor:

    quote [ _1 = phx::ref(author2name)[_1] ]
    

    Note also, assigning back to _1 is important!

  • Also, to have an auto-rule in the presence of Semantic Actions, you need to assign the rule using %= (otherwise Karma will suppress all automatic attribute propagation)

sehe
  • 374,641
  • 47
  • 450
  • 633
  • You can see me live-coding this answer (including trouble shooting steps!) here [in the recorded session](https://www.livecoding.tv/video/karma-rule-using-semantic-action/) ([experiment](http://chat.stackoverflow.com/transcript/10?m=24182469#24182469)) – sehe Oct 09 '15 at 19:28
  • Hey sehe, thanks for the answer, after combinig these steps, i figured out that there is a problem - my TYPEX is a enum class, now im getting kama_subrule compile failures - see http://coliru.stacked-crooked.com/a/c6f9a14fb8d8911f – Roby Oct 09 '15 at 19:38
  • 1
    Yeah, that's why you should post a [SSCCE](http://sscce.org) - so we don't have "make up shit". I'm sure you can just change things around: [Live On Coliru](http://coliru.stacked-crooked.com/a/aef35ac32a9fdc12) _(if you watch the livestream recording you will notice that I have this configuration somewhere during my refactorings. I simplified in the end.)_ – sehe Oct 09 '15 at 19:42
  • for my second question: http://coliru.stacked-crooked.com/a/42335ae00a5b0c3c why the headline fails ? – Roby Oct 10 '15 at 06:05
  • @Roby where did you post the second question? I've fixed it but I won't fit the explanation in a comment – sehe Oct 10 '15 at 17:46