在Boost Phoenix文章「轉換表達式樹」here中,使用了一組自定義類invert_actions
的專業化語言來轉換二進制算術表達式。例如a+b
變成a-b
; a*b
變成a/b
;反之亦然。轉換Boost C++ Phoenix表達式樹
這涉及表達式樹的遞歸遍歷 - 但是,當遇到涉及操作符未明確處理的表達式時,此遍歷停止。例如,_1+_2-_3
將變爲_1-_2+_3
,但_1+_1&_2
將保持原樣(&
沒有處理程序)。 let(_a = 1, _b = 2) [ _a+_b ]
也將保持不變。
我原以爲這是文章的打算,但看看最後列出的測試,我看到if_(_1 * _4)[_2 - _3]
預計會改變;與提供的代碼(here),我發現它沒有。
那麼我怎樣才能定義一個通用的Boost Phoenix表達式樹變換,它適用於所有明確列出的(n元)運算符集合的全部;讓其他人保持不變?
某些代碼可能有用。我想要下面的C++ 11代碼(自動)輸出0
,而不是2
; 沒有明確處理&
或任何其他操作員/語句。
#include <iostream>
#include <boost/phoenix.hpp>
#include <boost/proto/proto.hpp>
using namespace boost;
using namespace proto;
using namespace phoenix;
using namespace arg_names;
struct invrt {
template <typename Rule> struct when : proto::_ {};
};
template <>
struct invrt::when<rule::plus>
: proto::call<
proto::functional::make_expr<proto::tag::minus>(
evaluator(_left, _context), evaluator(_right, _context)
)
>
{};
int main(int argc, char *argv[])
{
auto f = phoenix::eval(_1+_1&_2 , make_context(make_env(), invrt()));
std::cout << f(1,2) << std::endl; // Alas 2 instead of 0
return 0;
}
謝謝@Eric Niebler,這真是太棒了 - 2種解決方案非常慷慨。我喜歡第一個使用proto,但第二個使用模板專業化使它很好地模塊化;說如果我想再次添加rule :: divides的情況。 – user2023370 2013-02-28 17:04:01