2013-03-05 22 views
5

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

举例来说,我已经建立在Boost Phoenix Starter Kit懒惰的函数部分,并创建了一个懒惰的新增功能:

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; 

我再准备一个简单的加至零下从previous question变换,这里显示:

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> > 
    > 
    > 
{}; 

然而,当我申请一个倒凤凰lambda表达,使用my_add,它的参数,如下图所示,它似乎预期的反转还没有实现。有没有一种推荐的方式来实现凤凰内的函数调用,这可以促进这种转换?

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; 
} 

回答

3

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

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

加号节点在哪里?对于Proto(和凤凰)来说,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! 
} 
+0

三江源。我猜想这是做到这一点的方法,但在构建这个想法之前需要一些保证。 – user2023370 2013-03-07 10:39:27

+0

p.s.我想'let'主体也可以是'_1 + _2'。 – user2023370 2013-03-07 10:40:20

+0

我认为/你会发现在更复杂的情况下,你需要为你的函数体创建一个新的范围;因此'let'。至少,我似乎回想起这个教训很难学,但是对于我的生活,我不能再记得原因了。 :-P – 2013-03-08 08:00:09

相关问题