Ant*_*all 6 c++ lambda boost-spirit c++11
我的目标是创建一个解决方法,以便我可以在Boost Spirit Qi语义操作中使用C++ 11 lambdas,同时仍然可以访问更多扩展的qi占位符集,例如qi :: _ pass或qi :: _ r1,必须从上下文对象手动提取它们.我希望避免为一些非平凡的解析逻辑编写Phoenix lambdas,更喜欢C++ 11 lambdas中更直接的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);
}
Run Code Online (Sandbox Code Playgroud)
(注意:我知道这个代码执行的特定任务对于直接的Phoenix结构会更简单,或者甚至可以通过Boost Spirit更新直接允许单参数C++ 11 lambda来完成,因为它只是使用解析后的值(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 &
)'
Run Code Online (Sandbox Code Playgroud)
只需告诉 Boost 您需要前沿编译器支持:[1]
#define BOOST_RESULT_OF_USE_DECLTYPE
Run Code Online (Sandbox Code Playgroud)
并且您希望使用 Phoenix 的 V3 版本:
#define BOOST_SPIRIT_USE_PHOENIX_V3
Run Code Online (Sandbox Code Playgroud)
它有效
原因:
在 Phoenix Actor中使用函数对象假设您的函数对象将有一个特殊的嵌套struct result模板或者实际上是一个简单的 typedef result_type。这称为 RESULT_OF 协议,请参见此处:
http://www.boost.org/doc/libs/1_55_0/libs/utility/utility.htm#result_of
此协议是 c++03 兼容性所必需的。然而,lambdas没有它。事实上,lambda 具有未指定的类型。这正是支持 lambda 的编译器也始终支持的原因之一decltype,因此不再需要 RESULT_OF 协议
在第二个上#define,您需要选择 Phoenix V3,因为 Phoenix V2 根本不实现对 lambda 的支持。默认情况下,出于历史/兼容性原因,Spirit V2 选择 Phoenix V2。在实践中,Phoenix V3 更加成熟并且修复了许多(很多)问题,所以我建议始终运行BOOST_SPIRIT_USE_PHOENIX_V3
某些编译器的最新版本可能不需要[1]
| 归档时间: |
|
| 查看次数: |
1985 次 |
| 最近记录: |