Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在Boost Phoenix表达式中变换函数体_C++_Templates_Boost_Boost Phoenix_Boost Proto - Fatal编程技术网

C++ 在Boost Phoenix表达式中变换函数体

C++ 在Boost Phoenix表达式中变换函数体,c++,templates,boost,boost-phoenix,boost-proto,C++,Templates,Boost,Boost Phoenix,Boost Proto,如何在Boost Phoenix表达式的转换中也包含函数体 例如,我构建了的Lazy Functions部分,并创建了一个Lazy addition函数: 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&g

如何在Boost Phoenix表达式的转换中也包含函数体

例如,我构建了的Lazy Functions部分,并创建了一个Lazy addition函数:

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;

答案很简单,你会踢自己。您编写的表达式转换知道如何将加号节点转换为减号节点。但是在传递给它的表达式中没有加号节点。再看看:

auto g = invrt()(phoenix::lambda(_a = 0)[my_add(_1,_2)]);
加号节点在哪里?对于Proto(以及Phoenix),
my_add
是不透明的。他们不知道里面有新的东西。他们怎么可能

==编辑====

相反,请考虑这一点,它符合您的意图:

#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!
}
#包括
#包括
#包括
名称空间proto=boost::proto;
名称空间phoenix=boost::phoenix;
使用名称空间phoenix::arg_名称;
使用名称空间phoenix::local_名称;
auto const my_add=phoenix::let(_a=_1,_b=_2)[_a+_b];
结构投资:
原型::或_<
什么时候<
加上,
proto::functional::make_expr(
invrt(proto::_左),invrt(proto:_右)
)
>,
proto::否则<
proto::nary_expr
>
>
{};
int main()
{
自动f=phoenix::lambda(_a=0)[my_add(_1,_2)];
auto g=invrt()(phoenix::lambda(_a=0)[my_add(_1,_2)];

std::我不能谢谢你。我猜这是一种方法,但在建立这个想法之前需要一些保证。另外,我猜
let
主体也可以是
\u 1+\u 2
。我/认为/你会发现,在更复杂的上下文中,你需要为你的函数主体创建一个新的范围;因此,
let
。至少,我似乎记得自己是如何艰难地学习这一课的,但就我的一生而言,我已经记不起为什么了。:-PYes,我有同样的感觉;为什么不直接使用
序列
(?),比如:
自动常量f2=(stmt1,stmt2)
。我倾向于
lambda
而不是
let
,但现在我惊讶地发现,我使用作用域的主要原因是它们将返回最后一个“语句”的值,同样适用于
序列
。嗯。再次感谢您,我相信您的判断,暂时使用作用域。然后,为了支持作用域,局部变量有时很好:)
auto g = invrt()(phoenix::lambda(_a = 0)[my_add(_1,_2)]);
#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!
}