Search code examples
c++boostboost-spirit-qiboost-phoenixboost-spirit-karma

Boost Karma object method call


as an extension to my question and the answer from sehe i want to call a function while generating my output.

I added the method bool isRoby() and modified the emp rule.

   #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;

        bool isRoby()
        {
          return name == "roby";
        };
    };

    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 << bool_[ BIND? ] ];

        }

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

I just found Phoenix Lazy, but seems not to match.


Solution

  • Assuming you make the isRoby const:

    bool isRoby() const { return name == "roby"; };
    

    You can use phx::bind:

    bool_ [ _1 = phx::bind(&Emp::isRoby, _val) ]
    

    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;
    
        bool isRoby() const { return name == "roby"; };
    };
    
    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 << bool_ [ _1 = phx::bind(&Emp::isRoby, _val) ] ];
        }
    
        Emp x{ "one", AUTHOR2 };
        author2name[AUTHOR2] = "TWO!";
        std::cout << karma::format(emp, x);
    }