Nell'articolo Boost Phoenix, "Trasformare l'albero delle espressioni", here, una serie di specializzazioni di una classe personalizzata invert_actions
, vengono utilizzate per invertire le espressioni aritmetiche binarie. Ad esempio a+b
diventa a-b
; a*b
diventa a/b
; e viceversa per entrambi.Trasformazione di un Boost C++ Phoenix Expression Tree
Ciò comporta un attraversamento ricorsivo dell'albero delle espressioni, tuttavia questa interruzione si interrompe quando si incontra un'espressione che coinvolge un operatore non gestito in modo esplicito. Ad esempio, _1+_2-_3
diventerà _1-_2+_3
, ma _1+_1&_2
rimarrà invariato (non è disponibile il gestore per &
). let(_a = 1, _b = 2) [ _a+_b ]
rimarrà invariato.
Avevo pensato che questo fosse come previsto dall'articolo, ma guardando i test elencati alla fine, vedo che if_(_1 * _4)[_2 - _3]
si prevede che cambi; con il codice fornito (here), trovo che non lo sia.
Come è possibile definire una trasformata generica dell'albero di espressioni Boost Phoenix che si applica a a tutti di un insieme di operatori esplicitamente elencati (n-ari); lasciando gli altri immutati?
Alcuni codici potrebbero essere utili. Mi piacerebbe che il seguente codice C++ 11 (auto) emettesse 0
, e non 2
; senza che gestisce esplicitamente lo &
o qualsiasi altro operatore/istruzione.
#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;
}
Grazie a @Eric Niebler, è davvero fantastico - 2 soluzioni sono molto generose. Mi piace il primo uso del proto, ma il secondo uso delle specializzazioni dei template lo rende piacevolmente modulare; dì se volevo aggiungere il caso per la regola :: divide di nuovo. – user2023370