我是新手以提升精神,我有以下问题:
#include <string>
#include <vector>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/bind.hpp>
using namespace boost::spirit;
using namespace std;
struct MyGrammar
: qi::grammar<string::const_iterator, string(), ascii::space_type> {
MyGrammar();
void myFun(const string& s);
private:
qi::rule<string::const_iterator, string(), ascii::space_type> myRule;
};
using namespace boost::spirit;
using namespace std;
MyGrammar::MyGrammar() : MyGrammar::base_type(myRule) {
using qi::_1;
myRule = int_ [boost::bind(&MyGrammar::myFun, this, _1)]; // fails
myRule = int_ [_val = _1]; // fine
}
void MyGrammar::myFun(const string& s){
cout << "read: " << s << endl;
}
int
main(){
}
第一次分配myRule
我得到编译错误,而第二次分配编译正常。
在第一种情况下,编译器会输出我不理解的大量错误消息。 最后它说:
boost_1_49_0/include/boost/bind/bind.hpp:318:9: error: no match for call to '(const boost::_mfi::mf1<void, MyGrammar, const std::basic_string<char>&>) (MyGrammar* const&, const boost::phoenix::actor<boost::spirit::argument<0> >&)'
boost_1_49_0/include/boost/bind/mem_fn_template.hpp:163:7: note: candidates are: R boost::_mfi::mf1<R, T, A1>::operator()(T*, A1) const [with R = void, T = MyGrammar, A1 = const std::basic_string<char>&]
boost_1_49_0/include/boost/bind/mem_fn_template.hpp:184:7: note: R boost::_mfi::mf1<R, T, A1>::operator()(T&, A1) const [with R = void, T = MyGrammar, A1 = const std::basic_string<char>&]
有什么想法吗? 非常感谢您的帮助!
答案 0 :(得分:5)
您不能使用来自不同bind
实现的占位符。 Boost中目前有三个bind
函数:
boost::bind
,由boost::lambda::bind
,由boost::phoenix::bind
,这是你应该用于Boost.Spirit boost::spirit::qi
(和boost::spirit::karma
)下的占位符与boost::phoenix::bind
使用的占位符相同,所以只需使用它。
哦,还有专业提示:在全局命名空间中停止你的using namespace std;
,最好是任何其他using指令。
答案 1 :(得分:3)
第一个问题是您将std::string
指定为合成属性,然后根据qi::int_
定义规则,其合成属性为int
。
第二个问题是,直接作为Spirit docs状态,非凤凰函子采用三个参数,而不是一个:
您可以使用Boost.Bind绑定成员函数。对于函数对象,允许的签名是:
void operator()(Attrib const&, unused_type, unused_type) const; void operator()(Attrib const&, Context&, unused_type) const; void operator()(Attrib const&, Context&, bool&) const;
第三个问题是你使用的是Spirit的Phoenix _1
占位符而不是boost::bind
的占位符(它实际上位于全局命名空间中)。
总之,这应该有效:
#include <string>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
struct MyGrammar :
qi::grammar<std::string::const_iterator, int(), ascii::space_type>
{
MyGrammar();
void myFun(int i, qi::unused_type, qi::unused_type);
private:
qi::rule<std::string::const_iterator, int(), ascii::space_type> myRule;
};
MyGrammar::MyGrammar() : MyGrammar::base_type(myRule)
{
myRule = qi::int_[boost::bind(&MyGrammar::myFun, this, _1, _2, _3)];
}
void MyGrammar::myFun(int const i, qi::unused_type, qi::unused_type)
{
std::cout << "read: " << i << '\n';
}
int main()
{
std::string const input = "42";
std::string::const_iterator first = input.begin(), last = input.end();
qi::phrase_parse(first, last, MyGrammar(), ascii::space);
}
话虽如此,除非您有一个非常具体的理由在这里使用boost::bind
,否则您应该使用boost::phoenix::bind
代替:
#include <string>
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
struct MyGrammar :
qi::grammar<std::string::const_iterator, int(), ascii::space_type>
{
MyGrammar();
void myFun(int i);
private:
qi::rule<std::string::const_iterator, int(), ascii::space_type> myRule;
};
MyGrammar::MyGrammar() : MyGrammar::base_type(myRule)
{
myRule = qi::int_[boost::phoenix::bind(&MyGrammar::myFun, this, qi::_1)];
}
void MyGrammar::myFun(int const i)
{
std::cout << "read: " << i << '\n';
}
int main()
{
std::string const input = "42";
std::string::const_iterator first = input.begin(), last = input.end();
qi::phrase_parse(first, last, MyGrammar(), ascii::space);
}
这允许绑定成员函数只取一个参数 - 合成属性 - 就像你原来想要的那样。