我的目标是创建一个解决方法,以便我可以在 Boost Spirit Qi 语义操作中使用 C++11 lambda,同时仍然可以访问更扩展的 qi 占位符集,例如 qi::_pass 或 qi::_r1,无需必须手动从上下文对象中提取它们。我希望避免为一些重要的解析逻辑编写 Phoenix lambda,而是更喜欢 C++11 lambda 中可用的更直接的 C++ 语法和语义。
下面的代码代表了我对解决方法的想法。这个想法是使用 phoenix::bind 绑定到 lambda 并将我需要的特定占位符传递给它。但是,我收到了一个非常长的模板化编译器错误(gcc 4.7.0,Boost 1.54),我没有专业知识来解释。我选择了我认为最相关的部分并将其发布在代码下方。
我想知道我在这段代码中尝试做的事情是否可以使用 Boost Spirit,以及是否有人可以为我解释错误消息并告诉我出了什么问题。
#include <string>
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace phoenix = boost::phoenix;
int main() {
std::string input{"test1 test2 test3 FOO!"};
typedef decltype(input.begin()) StringIter;
qi::rule<StringIter, std::string()> parser =
*(
qi::char_
[
phoenix::bind(
[] (char value) {
std::cerr << value << std::endl;
},
qi::_1
)
]
);
qi::parse(input.begin(), input.end(), parser);
}
(注意:我知道此代码执行的特定任务使用直接 Phoenix 构造会更简单,或者甚至可以通过允许直接使用单参数 C++11 lambda 的 Boost Spirit 更新来完成,因为它只使用解析后的值 (qi::_1)。不过,这是我想做的那种事情的一个很好的最小示例,如果我能让它工作,它应该很容易泛化。)
而且,一些编译器错误(通过 STLfilt):
test\testSpiritLearning.cpp:28:9: required from here
D:\programming\lib\boost\boost_1_54_0/boost/spirit/home/support/action_dispatch.hpp:178:13:
error: no match for call to '(
const boost::phoenix::actor<
boost::phoenix::composite<
boost::phoenix::detail::function_eval<1>
, boost::fusion::vector<
boost::phoenix::value<main()::<lambda(char &)> >
, boost::spirit::argument<0>, boost::fusion::void_
, boost::fusion::void_, boost::fusion::void_
, boost::fusion::void_, boost::fusion::void_
, boost::fusion::void_, boost::fusion::void_
, boost::fusion::void_
>
>
>
) (
boost::spirit::traits::pass_attribute<
boost::spirit::qi::char_class<
boost::spirit::tag::char_code<
boost::spirit::tag::char_
, boost::spirit::char_encoding::standard
>
>, char, void
>::type &
, boost::spirit::context<
boost::fusion::cons<basic_string<char> &, boost::fusion::nil>
, boost::fusion::vector0<>
> &, bool &
)'