5

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;

次に、前の質問からの単純なプラスからマイナスへの変換を準備します。これを次に示します。

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

1 に答える 1

3

答えは本当にとても簡単で、あなたは自分自身を蹴るつもりです。あなたが書いた式の変換は、プラスノードを減算ノードに変換する方法を知っています。ただし、渡す式にはプラスノードはありません。もう一度見てください:

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

プラスノードはどこにありますか?プロト(およびフェニックス)に対して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!
}
于 2013-03-07T01:02:21.463 に答える