I am trying to debug a simple struct which contains an enum class with BOOST_SPIRIT_DEBUG_NODE, but I always get the compile error "C:\boost\boost\spirit\home\support\attributes.hpp:1226: error: cannot bind 'std::basic_ostream' lvalue to 'std::basic_ostream&&' near 'out << val;'"
I don't know why I get a rvalue error like that, I tried to to add a manual overload for the operator<< for the enum class but that didn't work either.
I am using boost 1.55 and try to compile with gcc 4.8 with MinGW 32-bit on Windows 8.1 x64.
When I change the enum class to a default c++ enum it works, but I'd like to use the new enum classes for proper namespace handling.
I don't know why I get a rvalue error like that, I tried to to add a manual overload for the operator<< for the enum class but that didn't work either.
I think that required code, since that does work:
First, with a classic enum Live on Coliru
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <iostream>
namespace qi = boost::spirit::qi;
struct data_t
{
std::string label;
enum Choice { left, right, up, down } choice;
data_t(std::string label="default", Choice choice=left): label(std::move(label)), choice(choice) {}
friend std::ostream& operator<<(std::ostream& os, Choice const& v) {
switch(v) {
case left: return os << "left";
case right:return os << "right";
case up: return os << "up";
case down: return os << "down";
default: return os << "?";
}
}
friend std::ostream& operator<<(std::ostream& os, data_t const& v) {
return os << "{label:" << v.label << ";choice:" << v.choice << "}";
}
};
template <typename It, typename Skipper = qi::space_type>
struct parser : qi::grammar<It, data_t(), Skipper>
{
parser() : parser::base_type(start)
{
using namespace qi;
choice_.add
("left", data_t::left)
("right", data_t::right)
("up", data_t::up)
("down", data_t::down);
start %= as_string[ lexeme[+graph] ] >> lexeme [choice_];
BOOST_SPIRIT_DEBUG_NODE(start);
}
private:
qi::symbols<char, data_t::Choice> choice_;
qi::rule<It, data_t(), Skipper> start;
};
bool doParse(const std::string& input)
{
typedef std::string::const_iterator It;
auto f(begin(input)), l(end(input));
parser<It, qi::space_type> p;
data_t data;
try
{
bool ok = qi::phrase_parse(f,l,p,qi::space,data);
if (ok)
{
std::cout << "parse success\n";
std::cout << "data: " << data << "\n";
}
else std::cerr << "parse failed: '" << std::string(f,l) << "'\n";
if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
return ok;
} catch(const qi::expectation_failure<It>& e)
{
std::string frag(e.first, e.last);
std::cerr << e.what() << "'" << frag << "'\n";
}
return false;
}
int main()
{
bool ok = doParse("label1 up");
return ok? 0 : 255;
}
Second with an enum class Live on Coliru
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <iostream>
namespace qi = boost::spirit::qi;
struct data_t
{
std::string label;
enum class Choice { left, right, up, down } choice;
data_t(std::string label="default", Choice choice=Choice::left): label(std::move(label)), choice(choice) {}
friend std::ostream& operator<<(std::ostream& os, Choice const& v) {
switch(v) {
case Choice::left: return os << "left";
case Choice::right:return os << "right";
case Choice::up: return os << "up";
case Choice::down: return os << "down";
default: return os << "?";
}
}
friend std::ostream& operator<<(std::ostream& os, data_t const& v) {
return os << "{label:" << v.label << ";choice:" << v.choice << "}";
}
};
template <typename It, typename Skipper = qi::space_type>
struct parser : qi::grammar<It, data_t(), Skipper>
{
parser() : parser::base_type(start)
{
using namespace qi;
choice_.add
("left", data_t::Choice::left)
("right", data_t::Choice::right)
("up", data_t::Choice::up)
("down", data_t::Choice::down);
start %= as_string[ lexeme[+graph] ] >> lexeme [choice_];
BOOST_SPIRIT_DEBUG_NODE(start);
}
private:
qi::symbols<char, data_t::Choice> choice_;
qi::rule<It, data_t(), Skipper> start;
};
bool doParse(const std::string& input)
{
typedef std::string::const_iterator It;
auto f(begin(input)), l(end(input));
parser<It, qi::space_type> p;
data_t data;
try
{
bool ok = qi::phrase_parse(f,l,p,qi::space,data);
if (ok)
{
std::cout << "parse success\n";
std::cout << "data: " << data << "\n";
}
else std::cerr << "parse failed: '" << std::string(f,l) << "'\n";
if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
return ok;
} catch(const qi::expectation_failure<It>& e)
{
std::string frag(e.first, e.last);
std::cerr << e.what() << "'" << frag << "'\n";
}
return false;
}
int main()
{
bool ok = doParse("label1 up");
return ok? 0 : 255;
}
My guess is you forgot to add serialization to either your enum or your struct.