c++ - Boost::spirit 在继承属性中传递语义 Action

标签 c++ parsing boost grammar boost-spirit

我正在尝试在语法的继承参数中传递语义操作。

在下面这个非常基本的例子中,语法解析了两个数字,我将语义 Action (以 c++ lambda 的形式)传递给它,我希望在解析第一个数字时调用这个 Action 。但是它没有调用但被默默地忽略了,我想知道为什么会这样以及做这些事情的正确方法是什么。

#include <iostream>
#include <boost/spirit/include/qi.hpp>

using namespace std;
using namespace boost;

namespace qi = spirit::qi;
namespace phx = phoenix;

template <typename Iterator, typename Action>
struct two_numbers : qi::grammar<Iterator, void (Action const&)>
{
  two_numbers() : two_numbers::base_type(start)
  {
    using namespace qi;
    start = int_ [ _r1 ] >> ' ' >> int_;
  }
  qi::rule<Iterator, void (Action const&)> start;
};

int main ()
{
  string input { "42 21" };
  auto first=std::begin (input), last=std::end(input);

  static const auto my_action = [] (auto&& p) {
    cout << "the meaning of life is " << p << "\n";
  };

  static const two_numbers <decltype(first), decltype (my_action)> p;

  if (qi::parse (first, last, p(phx::ref(my_action))))
    cout << "parse ok\n";
}

预期的输出是:

the meaning of life is 42
parse ok

真正的输出是:

parse ok

最佳答案

首先,立即响应:

"I'm trying to pass semantic action in a grammar's inherited argument."

瞬间创伤性休克。你……你……什么?!

C++ 不太适合高阶编程,尤其是基于表达式模板的静态多态性。事实上是这样,但在我之前的回答中,我已经警告过在命名对象(≅ 变量)中存储表达式模板时不要使用 UB。

当时是 UB你发现的。在我看来,这很幸运。

最近,我已经遇到了另一个关于类似目标的问题:

请特别注意评论线程。我不认为这是一条明智的道路,至少在 Boost Mpl 完成 C++11 的全部优点(可能是 Boost Hana ?)和 Proto-0x 之前是这样。被释放。

到时候,Spirit X3大概已经成熟了,就剩下Boost Phoenix的差距了。我不确定这是否在任何人的议程上。

简而言之:我们将被困在这个“半途”的土地上,在那里我们可以拥有美好的事物,但有一些非常有限的限制。我们可能应该避免得意忘形,不要假装我们突然有能力用 C++ 编写 Haskell。

也相关:有一个提案 ( N4221, pdf ) 用于 C++ 中引用的通用生命周期扩展。它附带了一些简单应用的好例子,例如 Boost Range 适配器,这些适配器在当前 C++ 中是静默的 UB。例如。来自 §2.3 普遍观察:

std::vector<int> vec;
for (int val : vec | boost::adaptors::reversed
                   | boost::adaptors::uniqued) 
{
       // Error: result of (vec | boost::adaptors::reversed) died.
}

解决方案

也就是说,由于继承的参数将是一个仿函数(不是惰性 actor),您需要绑定(bind)它:

    start = int_ [ phx::bind(phx::cref(_r1), qi::_1) ] >> ' ' >> int_;

确实有效: Live On Coliru

但是,我不推荐这个

关于c++ - Boost::spirit 在继承属性中传递语义 Action ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26414677/

相关文章:

php解析错误 explode

ios - DDMath解析器 : How to define default values for variables

c++ - std::optional 和 boost::optional 是否遵守托管对象的对齐限制?

c++ - 以高效的方式创建、访问、存储和加载 boost::bimap

c++ - Qt5 QMainWindow组件删除

c++ - 新建 Win32 应用程序向导为空白

c++ - 用 Qt 替换 HTML 文件中的特殊占位符

c++ - GCC 有内置的编译时断言吗?

c++ - 有限状态机解析器

c++ - 为 Boost.Log 严重性记录器实例的接收器设置严重性过滤器