C++ Boost::spirit在继承属性中传递语义动作

C++ Boost::spirit在继承属性中传递语义动作,c++,parsing,boost,grammar,boost-spirit,C++,Parsing,Boost,Grammar,Boost Spirit,我试图在语法的继承参数中传递语义动作 在下面的基本例子中,语法解析两个数,并且我将语义动作(以C++的形式)传递给它,并且我希望这个动作在第一个数字的解析中被调用。然而,它没有呼叫,而是默默地忽略了,我想知道为什么会这样,以及做这些事情的正确方式是什么 #include <iostream> #include <boost/spirit/include/qi.hpp> using namespace std; using namespace boost; namesp

我试图在语法的继承参数中传递语义动作

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

#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

第一,立即回应:

“我试图在语法的继承参数中传递语义动作。”

瞬间创伤性休克。你。。。你。。。什么

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

那次是你发现的。在我看来,那是幸运的

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

请特别注意注释线程。我不认为这是一条明智的道路,至少在BoostMPL用完整的C++11实现并发布之前是这样

到那时,Spirit X3可能已经成熟了,我们只剩下了与Boost Phoenix的差距。我不确定这是否在任何人的议事日程上

简言之:我们将被困在这个“中途”地带,在那里我们可以拥有美好的东西,但有一些相当有限的限制。我们应该避免被遗忘,假装我们突然能够在C++中写哈斯克尔。

也有相关:C++中引用的广义生命周期扩展的建议()。它带有一些简单的应用,例如在当前C++中,UP是无声的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.
}
确实有效:


但是,我不推荐这个

强制性链接:在N4221提案中添加了一个链接(谢谢@AndyProwl)。谢谢你的回答。我修改了我的示例,现在传递了lazy-actor,但它仍然没有按预期工作:另外,如果由于早期破坏的prvalue和悬空引用而发生未定义的行为,您能在代码中准确显示问题引用是什么吗?@NikkiChumakov我不能(目前)。我可能找不到动机。不过,在BoostPhoenix中有一些东西可以告诉我们Phoenix表达式模板是否是“无状态的”(如果表达式的类型是默认可构造的,我大概记得是这种情况)。如果是这样,那么存储它就没有问题。否则,所有赌注都输光了。埃里克·尼布勒自己写了一篇文章详细介绍了这一点,IIRC。这可能就是我记得的那篇文章:。这里的目标稍有不同,因此您必须看穿它,才能了解它在这里是如何应用的。但是,我的静态lambda引用与我可能希望在语法的继承属性中传递的任何其他对象之间有什么区别呢?我的代码是什么?凤凰原型?C++?是的,情况非常类似于range::Adapters,当规范中没有任何内容使我们认为不可能将多个适配器组合到一个管道中时。不管怎样,谢谢你们提供的有趣的阅读列表,比如Boost.Hana和proposition,以及你们所提到的其他帖子。真有趣。
    start = int_ [ phx::bind(phx::cref(_r1), qi::_1) ] >> ' ' >> int_;