Domanda

Boost lambda permette di sovrascrivere tipo restituito dedotta utilizzando il modello ret<T>. Ho provato a cercare equivalente a Phoenix, ma non sono riuscito a trovarne uno.

C'è un equivalente a Phoenix? So come fare la mia sostituzione, ma preferirei non. grazie

È stato utile?

Soluzione

Rewrite:. Ho perso il punto sulla mia prima risposta (era tardi), mi permetta di provare di nuovo

Vi faccio un po 'di esposizione per le persone come me che potrebbe perdere il tuo punto la prima volta. In boost :: lambda, quando si utilizzano tipi definiti dall'utente nelle espressioni operatore, si deve utilizzare la funzione ret <> per esclusione tipo di ritorno deduzione. Questo perché il sistema di detrazione tipo di ritorno lambda supporta solo tipi nativi (e stl? Non mi ricordo) direttamente. Un breve esempio:

using namespace boost::lambda;

struct add_t{
    add_t(int i) : i(i) {};
    add_t operator+(const add_t& other) const{
        return add_t(i + other.i);
    }
    int i;
};

(_1 + _2)(add_t(38), add_t(4));           // RETURN TYPE DEDUCTION FAILS
ret<add_t>(_1 + _2)(add_t(38), add_t(4)); // OK

A Phoenix però, sono non sono necessari suggerimenti (nota che letterali e provvisori non-const non può apparire in una lista di argomenti phoenix):

using namespace boost::phoenix;

add_t i(38), j(4);
(_1 + _2)(i, j);    // JUST FINE

Il sistema di detrazione tipo di ritorno è completamente diversa e molto più naturale a Phoenix; sarà correttamente dedurre il tipo di ritorno di operatori che utilizzano la semantica convenzionali. In particolare, il tipo di ritorno deve corrispondere al tipo di uno degli operandi, essere un riferimento, puntatore o puntatore const ad uno dei tipi di argomento, o essere un iteratore contenitore STL / contenitore di uno di questi tipi. C'è una bella scrittura di tipo di ritorno Phoenix deduzione type_deduction.hpp intestazione per ulteriori dettagli.

Così ora sto leggendo la tua domanda come, come possono la semantica dell'operatore non convenzionali essere trattati in Phoenix?

Si consideri il seguente strana coppia di tipi come esempio

struct add_ret_t{
    add_ret_t(int i) : i(i) {};
    int i;
};

struct add_t{
    add_t(int i) : i(i) {};
    add_ret_t operator+(const add_t& other) const{
        return add_ret_t(i + other.i);
    }
    int i;
};

Per lambda, questo non è un problema, basta utilizzare la funzione di ret:

using namespace boost::lambda;

ret<add_ret_t>(_1 + _2)(add_t(38), add_t(4)); // OK

Ma Phoenix non può occuparsi di questo operatore (si può dare la colpa?), Perché il tipo di ritorno non è correlato agli argomenti, e non v'è alcun modo per indicare direttamente il tipo di ritorno a Phoenix. Se c'è una ragione buona per utilizzare un operatore come questo, un caso potrebbe essere aggiunto al sistema tipo di deduzione, ma non riesco a vedere un modo per fare questo senza l'hacking type_deduction.hpp o diramazione una buona parte di Phoenix.

In alternativa, ho capito un piccolo hack per sostituire le tipologie di ritorno per gli operatori specifici. Il result_of_ Operazione strutture template in boost / spirito / home / Phoenix / operatore / arithmetic.hpp (linee 39-56 elencano i tipi struct, spinta 1,43) eseguire il tipo di detrazione quando vengono istanziati e memorizzare i risultato. Quindi, tutto ciò che è necessario è quello di fornire alcune specializzazioni di template per le operazioni di problema, che devono solo contengono uno typedef specificando il tipo di ritorno. Esempio ( tastiera codici per la piena src ):

using namespace boost::phoenix;

namespace boost{ namespace phoenix{

//override add_t addition to give add_ret_t
template <> struct result_of_plus<add_t&, add_t&> { typedef add_ret_t type; };

//override int addition to give char
template <> struct result_of_plus<int&, int&> { typedef char type; };

}}

int main()
{
    add_t i = 1, j = 7;
    std::cout << ((_1 + _2)(i, j)).i << std::endl;

    int k = 51, l = 37;
    std::cout << ((_1 + _2)(k, l)) << std::endl;

    return 0;
}

Questo certamente non è un sostituto ret, ma in un certo senso il suo meglio sin dal suo globale. Se ci sono un sacco di operatori di sovraccarico, la serie completa di operazioni potrebbe essere macroed.

Altri suggerimenti

Per quanto ne so, questo (o qualcosa di simile) non è supportato a Phoenix. Se hai descritto il vostro caso d'uso potrei essere in grado di aiutare, però.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top