Boost Spirit QI中成员函数作为语义动作绑定时编译报错如何解决?
问题原因
- 核心是Boost Spirit QI的语义动作系统基于Phoenix函数式编程库实现,原生
boost::bind生成的绑定对象不满足Phoenix可调用对象的协议,编译时无法识别对应的result_type定义,触发你看到的类型错误。 - 其次你的
print成员函数定义了3个入参,你之前绑定的时候只传入了1个占位符qi::_1,参数数量不匹配也是编译失败的原因之一。
修复方案
方案1:使用Phoenix绑定并补齐占位符
将语义动作中的boost::bind替换为boost::phoenix::bind,同时补齐3个参数对应的占位符,另外需要将被绑定的对象调整为语法类的成员变量,避免局部变量生命周期结束后触发野指针问题,修改后代码如下:
template <typename Iterator> struct bd_parse_grammar : qi::grammar<Iterator> { template <typename TokenDef> bd_parse_grammar( TokenDef const& tok ) : bd_parse_grammar::base_type( start ) { start = *( tok.word[boost::phoenix::bind(&my_functor_word::print, &mfw, qi::_1, qi::_2, qi::_3)] ) ; } qi::rule<Iterator> start; my_functor_word mfw; // 移到类成员位置,生命周期和语法对象一致 };
不需要修改原有print成员函数的签名即可正常编译运行。
方案2:简化成员函数签名(推荐)
如果不需要用到后面两个unused参数,可以直接简化print成员函数的定义,Phoenix会自动忽略Spirit传入的多余参数,代码更简洁:
struct my_functor_word { void print ( std::string const& s ) const { std::cout << "word:" << s << std::endl; } }; // 语义动作只需要传1个占位符 tok.word[boost::phoenix::bind(&my_functor_word::print, &mfw, qi::_1)]
内容的提问来源于stack exchange,提问作者John Pierce
相关产品推荐
相关产品推荐

