修复该规则声明后:
typedef boost::function<char(char const*)> Func;
qi::rule<Iterator, Func()> start;
它起作用了:Live On Coliru (c++03)。
更新:
为什么我最终得到了如此复杂的装置?
qi::_val = px::bind(px::lambda[arg1[arg2]], px::lambda[arg1], qi::_1)
出色地。让我告诉您将函数组合与惰性求值复杂化的乐趣(在 C++ 模板元编程中,具有引用/值语义的这些惊喜):不要执行以下操作:
qi::_val = px::lambda(_a = qi::_1) [arg1[_a]] // UB!!! DON'T DO THIS
根据编译器、优化级别,这可能*似乎有效。但它正在调用 Undefined Behavior [1]。问题是qi::_1
它将被保留为对解析器表达式公开的属性的引用。qi::int_
但是,在解析器上下文的生命周期结束后,此引用是悬空引用。
因此,通过无效引用评估函子间接。为了避免这种情况,你应该说(Live On Coliru):
qi::_val = px::lambda(_a = px::val(qi::_1)) [arg1[_a]]
甚至(如果你喜欢晦涩的代码):
qi::_val = px::lambda(_a = +qi::_1) [arg1[_a]]
或者,您知道,您可以坚持使用绑定的嵌套 lambda,因为绑定默认为值语义 for qi::_1
(除非您使用phx::cref
/phx::ref
包装器)。
我希望上述分析能够让我明白我之前在评论中提出的观点:
请注意,我不推荐这种代码风格。使用 Phoenix 进行高阶编程已经足够棘手,无需在某些嵌入式表达式模板 DSL 中从惰性 actor 中组合它们:qi::_val = px::bind(px::lambda[arg1[arg2]], px::lambda[arg1], qi::_1)
. '纳夫说?
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/function.hpp>
namespace qi = boost::spirit::qi;
namespace px = boost::phoenix;
typedef boost::function<char(char const*)> Func;
int main()
{
typedef std::string::const_iterator Iterator;
using namespace boost::phoenix::arg_names;
qi::rule<Iterator, Func()> start;
start = qi::int_
[ qi::_val = px::bind(px::lambda[arg1[arg2]], px::lambda[arg1], qi::_1) ];
// or: [ qi::_val = px::lambda(_a = px::val(qi::_1))[arg1[_a]] ];
static char const* inputs[] = { "0", "1", "2", "3", "4", 0 };
for (char const* const* it = inputs; *it; ++it)
{
std::string const input(*it);
Iterator f(input.begin()), l(input.end());
Func function;
bool ok = qi::parse(f, l, start, function);
if (ok)
std::cout << "Parse resulted in function() -> character "
<< function("Hello") << "; "
<< function("World") << "\n";
else
std::cout << "Parse failed\n";
if (f != l)
std::cout << "Remaining unparsed: '" << std::string(f, l) << "'\n";
}
}
印刷
Parse resulted in function() -> character H; W
Parse resulted in function() -> character e; o
Parse resulted in function() -> character l; r
Parse resulted in function() -> character l; l
Parse resulted in function() -> character o; d
[1] (MSVC2013 出现崩溃,gcc 可能在 -O3 中工作,但在 -O0 等中出现段错误)