简体   繁体   English

在Boost Phoenix表达式中转换函数体

[英]Transforming Function Bodies within Boost Phoenix Expressions

How can I also include function bodies in a transformation of a Boost Phoenix expression? 如何在Boost Phoenix表达式的转换中包含函数体?

For example, I have built on the Lazy Functions section of the Boost Phoenix Starter Kit , and created a lazy addition function: 例如,我构建了Boost Phoenix Starter Kit的Lazy Functions部分,并创建了一个延迟添加函数:

struct my_lazy_add_impl {
  typedef int result_type;
  template <typename T>
  T operator()(T x, T y) const { return x+y; }
};
phoenix::function<my_lazy_add_impl> my_add;

I then prepare a simple plus-to-minus transform from a previous question , shown here: 然后,我从前一个问题准备一个简单的加号 - 减号变换,如下所示:

struct invrt:
  proto::or_<
    proto::when<
      proto::plus<proto::_, proto::_>,
      proto::functional::make_expr<proto::tag::minus>(
        invrt(proto::_left), invrt(proto::_right)
      )
    >,
    proto::otherwise<
      proto::nary_expr<proto::_, proto::vararg<invrt> >
    >
  >
{};

However, when I apply an inverted Phoenix lambda expression, using my_add , to its arguments, as shown below, it seems the intended inversion has not been achieved. 但是,当我将一个倒置的Phoenix lambda表达式(使用my_add )应用于其参数时,如下所示,似乎尚未实现预期的反转。 Is there a recommended way to implement function calls within Phoenix, which can facilitate such transformations? 是否有推荐的方法在Phoenix中实现函数调用,这可以促进这种转换?

int main(int argc, char *argv[])
{
  auto f =         phoenix::lambda(_a = 0)[my_add(_1,_2)];
  auto g = invrt()(phoenix::lambda(_a = 0)[my_add(_1,_2)]);
  std::cout << f()(1,2) << std::endl; // 3
  std::cout << g()(1,2) << std::endl; // 3 again; alas not -1
  return 0;
}

The answer is really very simple and you're going to kick yourself. 答案非常简单,你会踢自己。 The expression transformation you wrote knows how to convert a plus node into a subtract node . 您编写的表达式转换知道如何将加号节点转换为减法节点 But there is no plus node in the expression you're passing to it. 但是你传递给它的表达式中没有加号节点。 Look again: 再看一遍:

auto g = invrt()(phoenix::lambda(_a = 0)[my_add(_1,_2)]);

Where's the plus node? 哪个是加号节点? To Proto (and to Phoenix), my_add is opaque. 对于Proto(和Phoenix), my_add是不透明的。 They don't know there's an addition going on inside there. 他们不知道那里有一个额外的东西。 How could they? 他们怎么样?

====EDIT==== ==== ====编辑

Consider this instead, which does what you intend: 相反,请考虑这一点,这符合您的意图:

#include <iostream>
#include <boost/phoenix.hpp>
#include <boost/proto/proto.hpp>
namespace proto = boost::proto;
namespace phoenix = boost::phoenix;
using namespace phoenix::arg_names;
using namespace phoenix::local_names;

auto const my_add = phoenix::let(_a = _1, _b = _2)[_a + _b];

struct invrt:
  proto::or_<
    proto::when<
      proto::plus<proto::_, proto::_>,
      proto::functional::make_expr<proto::tag::minus>(
        invrt(proto::_left), invrt(proto::_right)
      )
    >,
    proto::otherwise<
      proto::nary_expr<proto::_, proto::vararg<invrt> >
    >
  >
{};

int main()
{
  auto f =         phoenix::lambda(_a = 0)[my_add(_1,_2)];
  auto g = invrt()(phoenix::lambda(_a = 0)[my_add(_1,_2)]);

  std::cout << f()(1,2) << std::endl; // 3
  std::cout << g()(1,2) << std::endl; // -1, w00t!
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM