use*_*370 5 c++ templates boost boost-phoenix boost-proto
如何在Boost Phoenix表达式的转换中包含函数体?
例如,我构建了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;
Run Code Online (Sandbox Code Playgroud)
然后,我从前一个问题准备一个简单的加号 - 减号变换,如下所示:
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> >
>
>
{};
Run Code Online (Sandbox Code Playgroud)
但是,当我应用倒置凤凰lambda表达式时,my_add如下所示使用其参数,似乎尚未实现预期的反转.是否有推荐的方法在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;
}
Run Code Online (Sandbox Code Playgroud)
答案真的很简单,你会踢自己的。您编写的表达式转换知道如何将加节点转换为减节点。但是您传递给它的表达式中没有加号节点。再看一下:
auto g = invrt()(phoenix::lambda(_a = 0)[my_add(_1,_2)]);
Run Code Online (Sandbox Code Playgroud)
加号节点在哪里?对于 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!
}
Run Code Online (Sandbox Code Playgroud)