2013-03-05 7 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は不透明です。彼らはそこに追加があることを知らない。彼らはどうでしたか?

==== ==== EDIT

はあなたが意図し何をしている、代わりにこれを考えてみましょう:

#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'本体も' _1 + _2'と考えています。 – user2023370

+0

私はあなたの関数本体の新しいスコープを作成する必要があるより複雑なコンテキストでそれを見つけるでしょう。それゆえ、「let」。少なくとも、私はこのレッスンを難しい方法で学ぶことを思い出しているようですが、私の人生にとって、私はもはや理由を覚えていません。 :-P –