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?
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 intostd::string
attributes. The good thing here is that the input can be reflected unaltered (e.g.qi::raw[ qi::int_ >> ';' >> qi::double_ ]
will workIn your case you can probably use
as_string[]
. But you can also fix the argument to take astd::vector<char> const&
Finally you could use
attr_cast<>
to achieve exactly the same effect as with the separateqi::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.