I have defined a boost::spirit::qi rule:
boost::spirit::qi::rule<Iterator, Identifier()> id;
where Identifier is defined by:
BOOST_STRONG_TYPEDEF(std::string, Identifier)
but when I use
BOOST_SPIRIT_DEBUG_NODE(id);
It fails to compile with following error:
boost_1_51_0/boost/spirit/home/support/attributes.hpp:1203: error: no match for 'operator<<' in 'out << val'
and it lists the overloaded operators of ostream.
Knowing that BOOST_STRONG_TYPEDEF defines a cast operator to the original type, shouldn't
compiler implicitly cast from Identifier to std::string when using operator<<
? or is there a restriction that prevents compiler to apply a cast operator of a type when it is trying to match the other operator (namely operator<<
)?
When I define the following operator it compiles:
inline std::ostream& operator<<(std::ostream& os, const Identifier& id)
{
return os << static_cast<std::string const&>(id);
}
I am using gcc4.4.2
This has nothing to do with boost, strong_typedef or spirit.
It has a lot to do with type deduction for template arguments. In short, when argument types are deduced, implicit conversions never take place [1]
Cf.:
No problem! Replace
double
bystd::string
, and it doesn't work anymore. What's different?The declaration of the streaming operator differs.
Contrast
To
The fact that the operator overload is a function template disallows any implicit conversions.
[1] I guess
initializer_list
may look like a bit of an exception here, what with widening/narrowing that it can do. Different subject, though