I fail to compile code in debug mode (code with BOOST_SPIRIT_DEBUG_NODE(my_rule)) when my_rule has some local variable of custom type.
- First version with rule
qi::locals<std::string>
is OK - Second version with rule
qi::locals<std::string,int>
is still OK - Current version with rule
qi::locals<std::string,std::vector<int> >
does not compile.
error: no match for operator<<
(operand types are std::basic_ostream<char>
and const std::vector<int>
)
I declare streaming operator<<
:
std::ostream& > operator<< (std::ostream& os, std::vector<int> const& art)
But It still does not compile.
I use boost 1_64_0. Here is the smallest complete code:
#define BOOST_SPIRIT_DEBUG
#if !defined(BOOST_SPIRIT_DEBUG_OUT)
#define BOOST_SPIRIT_DEBUG_OUT std::cerr
#endif
#include <tuple>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <iostream>
#include <string>
#include <vector>
// To solve the pb of declaration of grammar with locals
#include <typeinfo>
std::ostream&
operator<< (std::ostream& os, std::vector<int> const& art)
{
os << "[";
for( auto it = art.begin(); it != art.end() ; it++ ) {
os << *it << ",";
}
os << "]";
return os;
}
namespace client
{
namespace phoenix = boost::phoenix;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
using phoenix::val;
using namespace qi::labels;
using qi::_val;
using qi::_1;
// Our number list parser
template <typename Iterator>
struct mini_wkart_grammar
// first version: : qi::grammar<Iterator, int(), qi::locals<std::string>, ascii::space_type>
// second version: : qi::grammar<Iterator, int(), qi::locals<std::string,int>, ascii::space_type>
: qi::grammar<Iterator, std::vector<int>(), qi::locals<std::string,std::vector<int> >, ascii::space_type>
{
mini_wkart_grammar() : mini_wkart_grammar::base_type(start,"numbers")
{
using phoenix::push_back;
// first version: start= (qi::int_ >> qi::char_(',') >> qi::int_)[_val=_1+_3];
// second version: start= (qi::int_[_b=_1] >> qi::char_(',') >> qi::int_[_b+=_1])[_val=_b];
start= (qi::int_[push_back(_b,_1)] >> qi::char_(',') >> qi::int_[push_back(_b,_1)])[_val=_b];
BOOST_SPIRIT_DEBUG_NODE(start);
}
// first version OK: qi::rule<Iterator, int(), qi::locals<std::string>, ascii::space_type> start;
// second version OK: qi::rule<Iterator, int(), qi::locals<std::string,int>, ascii::space_type> start;
qi::rule<Iterator, std::vector<int>(), qi::locals<std::string,std::vector<int> >, ascii::space_type> start;
};
}
////////////////////////////////////////////////////////////////////////////
// Main program
////////////////////////////////////////////////////////////////////////////
int
main()
{
std::cout << "/////////////////////////////////////////////////////////\n\n";
std::cout << "\t\tA comma separated list parser for Spirit...\n\n";
std::cout << "/////////////////////////////////////////////////////////\n\n";
std::cout << "Give me a comma separated list of numbers.\n";
std::cout << "Type [q or Q] to quit\n\n";
// std::string result;
// first ans second version: int result;
std::vector<int> result;
std::string str;
using boost::spirit::ascii::space;
client::mini_wkart_grammar<std::string::const_iterator> wkart_grammar;
while (getline(std::cin, str))
{
if (str.empty() || str[0] == 'q' || str[0] == 'Q')
break;
std::string::const_iterator iter = str.begin();
std::string::const_iterator end = str.end();
// if (client::parse_numbers(str.begin(), str.end()))
if (boost::spirit::qi::phrase_parse(iter, end, wkart_grammar, space, result))
{
std::cout << "-------------------------\n";
std::cout << "Parsing succeeded\n";
std::cout << result << " Parses OK: " << std::endl;
}
else
{
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "-------------------------\n";
}
}
std::cout << "Bye... :-) \n\n";
return 0;
}
I think miss something in the operator declaration?
Thanks for any help..
First Off...
What are you trying to achieve anyways? That whole grammar could be
start = qi::int_ % ',';
and still have the exact same effect. See Boost Spirit: “Semantic actions are evil”?Your Question:
Sadly you need to make that
operator<<
ADL-enabled. (http://en.cppreference.com/w/cpp/language/adl)Since the element type is primitive, there is no associated namespace. So the only namespace that will be tried is
namespace ::std
which declaredstd::vector<>
.That might have undesired side effects, you you may want to force the issue with a hack:
See it Live On Wandbox