[英]boost spirit debug rule with locals
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. 当my_rule具有一些自定义类型的局部变量时,我无法在调试模式下编译代码(BOOST_SPIRIT_DEBUG_NODE(my_rule)代码)。
qi::locals<std::string>
is OK 规则为qi::locals<std::string>
第一个版本可以 qi::locals<std::string,int>
is still OK 规则为qi::locals<std::string,int>
第二版仍然可以 qi::locals<std::string,std::vector<int> >
does not compile. 规则为qi::locals<std::string,std::vector<int> >
当前版本无法编译。 error: no match for operator<<
(operand types are std::basic_ostream<char>
and const std::vector<int>
) 错误: operator<<
不匹配(操作数类型为std::basic_ostream<char>
和const std::vector<int>
)
I declare streaming operator<<
: 我声明流operator<<
:
std::ostream& > operator<< (std::ostream& os, std::vector<int> const& art)
But It still does not compile. 但是它仍然无法编译。
I use boost 1_64_0. 我使用升压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.. 谢谢你的帮助..
What are you trying to achieve anyways? 您到底想达到什么目的? That whole grammar could be start = qi::int_ % ',';
整个语法可以是start = qi::int_ % ',';
and still have the exact same effect. 并且仍然具有完全相同的效果。 See Boost Spirit: “Semantic actions are evil”? 参见Boost Spirit:“语义行为是邪恶的”?
Sadly you need to make that operator<<
ADL-enabled. 可悲的是,您需要使该operator<<
启用ADL。 ( http://en.cppreference.com/w/cpp/language/adl ) ( 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 declared std::vector<>
. 因此,将尝试使用的唯一命名空间是namespace ::std
,它声明了std::vector<>
。
namespace std {
std::ostream &operator<<(std::ostream &os, vector<int> const &art) {
os << "[";
for (auto it = art.begin(); it != art.end(); it++) {
os << *it << ",";
}
os << "]";
return os;
}
}
That might have undesired side effects, you you may want to force the issue with a hack: 这可能会产生不希望有的副作用,您可能需要使用hack来强制解决该问题:
namespace ADL_Hack {
template <typename T>
struct allocator : std::allocator<T> { };
}
template <typename T>
using Vector = std::vector<T, ADL_Hack::allocator<T> >;
namespace ADL_Hack {
template <typename... Ts>
std::ostream &operator<<(std::ostream &os, std::vector<Ts...> const &art) {
os << "[";
for (auto it = art.begin(); it != art.end(); it++) {
os << *it << ",";
}
os << "]";
return os;
}
}
See it Live On Wandbox 在魔盒上直播
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.