How do I convert boost::spirit::qi::lexeme's attribute to std::string?

884 views Asked by At

Consider:

struct s {
  AttrType f(const std::string &);
};

...and a rule r with an attribute AttrType:

template <typename Signature> using rule_t =
  boost::spirit::qi::rule<Iterator,
                          Signature,
                          boost::spirit::qi::standard::space_type>;

rule_t<AttrType()> r;

r = lexeme[alnum >> +(alnum | char_('.') | char_('_'))][
      _val = boost::phoenix::bind(&s::f, s_inst, _1)
    ];

When compiling this (with clang), I get this error message:

boost/phoenix/bind/detail/preprocessed/member_function_ptr_10.hpp:28:72: error: no viable conversion from
      'boost::fusion::vector2<char, std::__1::vector<char, std::__1::allocator<char> > >' to 'const std::__1::basic_string<char>'
                return (BOOST_PROTO_GET_POINTER(class_type, obj)->*fp)(a0);
                                                                       ^~

It's my impression that the problem is the type of the placeholder variable, _1. Is there a concise way to convert lexeme's attribute to std::string for this purpose?

If I interject an additional rule with an attribute type of std::string, it compiles:

rule_t<std::string()> r_str;

r = r_str[boost::phoenix::bind(&s::f, s_inst, _1)];
r_str = lexeme[alnum >> +(alnum | char_('.') | char_('_'))];

...but this seems a bit awkward. Is there a better way?

1

There are 1 answers

1
sehe On BEST ANSWER

You can use qi::as_string[] (which will coerce the attribute into a string if a suitable automatic transformation exists).

Alternatively you can use qi::raw[] which exposes the source-iterator range. This will automatically transform into std::string attributes. The good thing here is that the input can be reflected unaltered (e.g. qi::raw[ qi::int_ >> ';' >> qi::double_ ] will work

In your case you can probably use as_string[]. But you can also fix the argument to take a std::vector<char> const&


Finally you could use attr_cast<> to achieve exactly the same effect as with the separate qi::rule<> (but without using the separate rule :)) but I don't recommend it for efficiency and because older versions of boost had bugs in this facility.