2012-03-04 9 views
6

Vorrei riutilizzare il codice scrivendo un proto trasformare che è templato da un puntatore a funzione:Come si scrive una proto trasformazione basata su una funzione?

template <typename Ret, typename A0, typename A1, Ret func(A0,A1)> 
struct apply_func : proto::callable 
{ 
    // Do something with func 
}; 

Tuttavia, la funzione stessa è polimorfa quindi non voglio specificare la sua firma esatto.

Segue una versione semplificata di quello che vorrei che il mio codice assomiglia (sto usando trasformazioni esterne per un motivo tecnico che ritengo non correlato alla mia domanda corrente: non ho potuto far funzionare la ricorsione senza di loro):

template<typename R, typename A0, typename A1> 
R plus_func(A0 lhs, A1 rhs) { return lhs+rhs; } 

template<typename R, typename A0, typename A1> 
R minus_func(A0 lhs, A1 rhs) { return lhs-rhs; } 

struct my_grammar; 
struct plus_rule : proto::plus<my_grammar, my_grammar> {}; 
struct minus_rule : proto::minus<my_grammar, my_grammar> {}; 

struct my_grammar 
: proto::or_< 
    proto::when<proto::terminal<proto::_>, proto::_value> 
, proto::when<plus_rule, proto::external_transform > 
, proto::when<minus_rule, proto::external_transform > 
> 
{}; 

struct my_external_transforms 
    : proto::external_transforms< 
     proto::when<plus_rule, apply_func<plus_func>(my_grammar(proto::_left),my_grammar(proto::_right), proto::_state)> 
    , proto::when<minus_rule, apply_func<minus_func>(my_grammar(proto::_left),my_grammar(proto::_right), proto::_state)> 
    > 
{}; 

Questo non viene compilato perché mancano argomenti al modello appy_func. C'è una soluzione?

risposta

3

avete problemi multiple nel codice:

  • non si può prendere un puntatore a funzione template senza specificare il suo parametro modello come il modello non esisterà fino a quando la funzione get istanziare.
  • secondo punto, Ret (A, B) è un tipo di funzione non un tipo di puntatore di funzione.
  • il puntatore di funzione è un po 'grezzo come va l'astrazione, lo stesso può essere ottenuto da un funtore che risolve anche il tuo problema come un oggetto di fusione polimorfico è un singolo, non tipo di modello.
  • punto finale tecnico, la trasformazione del modello non può usare proto :: callable, devi specializzare boost :: proto :: is_callable esplicitamente. Ciò è dovuto a una limitazione della langauge su come viene rilevata l'ereditarietà.

Sfogliando il codice pseudo, vado per qualcosa di simile:

struct plus_func 
{ 
    template<class Sig> struct result; 

    template<class This,class A, class B> 
    struct result<This(A,B)> 
    { 
    typedef /*whatever*/ type; 
    }; 

    template<class A, class B> 
    typename result<plus_func(A const&,B const&)>::type 
    plus_func(A const& lhs, B const& rhs) 
    { 
    return lhs+rhs; 
    } 
}; 

struct minus_func 
{ 
    template<class Sig> struct result; 

    template<class This,class A, class B> 
    struct result<This(A,B)> 
    { 
    typedef /*whatever*/ type; 
    }; 

    template<class A, class B> 
    typename result<minus_func(A const&,B const&)>::type 
    plus_func(A const& lhs, B const& rhs) 
    { 
    return lhs-rhs; 
    } 
}; 

struct my_grammar; 
struct plus_rule : proto::plus<my_grammar, my_grammar> {}; 
struct minus_rule : proto::minus<my_grammar, my_grammar> {}; 

struct my_grammar 
: proto::or_< 
    proto::when<proto::terminal<proto::_>, proto::_value> 
, proto::when<plus_rule, proto::external_transform > 
, proto::when<minus_rule, proto::external_transform > 
> 
{}; 

struct my_external_transforms 
    : proto::external_transforms< 
     proto::when<plus_rule, apply_func<plus_func>(my_grammar(proto::_left),my_grammar(proto::_right), proto::_state)> 
    , proto::when<minus_rule, apply_func<minus_func>(my_grammar(proto::_left),my_grammar(proto::_right), proto::_state)> 
    > 
{}; 

Tipo restituito da ciascun PFO deve essere calcolato o specificato. Fai attenzione che A, B può essere const/ref qualificato e potrebbe aver bisogno di stripping prima di eseguire il calcolo del tipo.

Sidenote: external_transform non è richiesto affatto per le regole ricorsive. Immagino che il punto 4 (modello chiamabile) sia ciò che lo ha fatto non funzionare.

+0

Speravo di trovare una soluzione che consentisse all'utente di specificare più_func e meno_func in modo più conciso (non mi dispiace complicare le altre parti). Capisco dal tuo primo punto che questo non è possibile - Non posso prendere una funzione libera basata su modelli e trasformarla in un funtore polimorfico. Destra? –

+0

Oh, vedo la mia confusione. Grazie per l'aiuto. –

+0

Nota che con C++ 11, il plus_func potrebbe essere piuttosto facile da scrivere usando auto/decltype e non richiede la struttura di supporto risultato <>. Ora, l'oggetto funzione polimorfico è un'astrazione piuttosto ordinata che aiuta a incapsulare il modello come il functor in una struttura non di template. In C++ 03 questo è praticamente lo scatto migliore che hai e Proto è fatto per riconoscerli immediatamente. –

Problemi correlati