2013-03-05 6 views
5

어떻게하면 부스트 피닉스 표현식의 변환에 함수 본문을 포함시킬 수 있습니까?부스트 피닉스 표현식 내의 변환 함수 몸체

예를 들어, 나는 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에서 변환, 여기에 표시를 : 나는 다음과 같이 인수에 my_add를 사용하여 역 피닉스 lambda 표현, 적용 할 때

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

그러나, 의도 된 반전이 달성되지 않은 것 같다. 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; 
} 

답변

3

답변은 정말 간단하며 스스로 차버릴 것입니다. 여러분이 작성한 표현식 변환은 더하기 노드을 뺄셈 노드으로 변환하는 방법을 알고 있습니다. 그러나 전달할 표현식에는 더하기 노드가 없습니다. 다시보기 :

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! 
} 
+0

감사합니다를 :

==== 편집 ====

당신이하려는 것을 수행하는 대신에 이것을 고려하십시오. 나는 이것이 이것을하는 길이었다고 생각했지만, 아이디어를 쌓기 전에 약간의 안심을 원했다. – user2023370

+0

p.s. 나는'let' body가'_1 + _2' 일 수도 있다고 생각합니다. – user2023370

+0

나는 더 복잡한 상황에서 함수 본문에 대한 새로운 범위를 만들어야한다는 것을 알게 될 것이다. 그러므로 'let'. 적어도, 나는이 수업을 힘든 방법으로 배우는 것을 기억하지만, 내 인생에서 나는 더 이상 기억할 수 없다. :-P –