2010-10-07 14 views
6

Stavo solo cercando una classe base utile per un insieme di funtori basati sul take e int e sul return void.Perché unary_function non definisce operator()?

Pensando di utilizzare std/funzionale i funtori saranno in pratica unary_function<int,void> con operator().

Perché virtual result_type operator()(const argument_type& _Left) const = 0; non è definito nel modello unary_function? Immagino che sia perché potrebbero esserci variazioni di costanza ...
C'è qualche altro modello che ho perso che include lo operator()?

Non l'ho fatto da un po ', mi manca qualcosa?

Come dovrei anche fare uso di esistere funzionale come

std::ptr_fun< HWND, void >(someFunction); 
std::pointer_to_unary_function<HWND, void>(someFunction); 

EDIT: Forse dovrei includere l'altra metà l'utilizzo per fare questo completo. Forse è la metà di utilizzo che non si adatta al concetto.

Come si passa il functor a un metodo e lo si utilizza?

typedef unary_function<int,void> Functor; 

void DoStuff(const Functor& functor) { 
    int demo = 1; 
    functor(demo); 
} 

functor come unary_function non definisce operator() e quindi DoStuff non viene compilato.

risposta

10

I concetti di modello sono tipografici. Il fatto che una classe che soddisfa il concetto UnaryFunction abbia bisogno di operator() è specificata nella documentazione e dedotta dai modelli che utilizzano parametri di modello che soddisfano tale concetto. Non è necessario specificare la firma della funzione o richiedere che sia virtual, che prenda un parametro di riferimento const o che sia una funzione membro const.

Il modello unary_function non deve essere pensato come un'interfaccia (e non è progettato come uno). Non è certamente una classe di base polimorfa. È un aiuto, che viene utilizzato dalle classi che desiderano implementare il concetto AdaptableUnaryFunction.

Dalla documentazione STL, che sono affidabili per il razionale disegno originale: "L'unica ragione per cui esiste è quello di rendere la definizione delle funzioni unarie adattabili più conveniente" - http://www.sgi.com/tech/stl/unary_function.html

Lo standard è simile: "Le seguenti classi sono fornito di semplificare le typedef dell'argomento e il risultato tipi"(20.3.1/1)

uso avanzato - in realtà ciò che è necessario per UnaryFunction è che se f è un oggetto funzione unario, e x è convertibile al tipo di argomento, quindi f(x) è un'espressione valida del tipo di risultato. Non è necessario avere un argomento di tipo operator(), va bene avere un doppio argomento operator() con il secondo arg che ha un valore predefinito. Prova a definirlo come una pura funzione virtuale ;-)

Seconda domanda, fai uso di ptr_fun semplicemente chiamandolo con nome funzione/puntatore. I parametri del modello verranno dedotti dal tipo di funzione, quindi non è necessario specificarli.Il risultato è un oggetto del corrispondente tipo di modello pointer_to_unary_function.

Per utilizzare l'esempio direttamente dalla documentazione STL:

transform(first, last, first, 
    compose1(negate<double>, ptr_fun(fabs))); 

Questo è approssimativamente equivalente a:

for (auto current = first; current != last; ++current) { 
    *current = -fabs(*current); 
} 

(dove uso auto nella sua C++ 0x senso, che significa" non può essere disturbato/è impossibile scrivere il tipo di iteratore qui ")

Un nome/puntatore di funzione può essere utilizzato in transform (che prende unoParametro modello), ma non in compose1 (che accetta un parametro modello AdapatableUnaryFunction). Quindi senza ptr_fun, non c'è modo di comporre negate con fabs.

In risposta al tuo Modifica, sottolineo, unary_function non è una classe di base polimorfa. Non è possibile utilizzarlo utilmente (o nessuna delle sue istanziazioni) come un tipo di parametro di funzione.

Se si desidera utilizzare i concetti UnaryFunction o AdaptableUnaryFunction, allora è necessario scrivere un modello di funzione:

template <typename UnaryFunction> 
void DoStuff(UnaryFunction &functor) { 
    int demo = 1; 
    functor(demo); 
} 

Ciò richiede solo che il funtore prendere un tipo che int converte, però. Non richiede che ci vuole esattamente int e restituire esattamente void. Di solito è un vantaggio.

Se un modello non fa quello che vuoi, allora unary_function non fa per te. Non hai perso nulla: puoi progettare la tua interfaccia con un virtual operator(), ma le librerie standard non mirano a fornire nulla del genere.

+0

Grazie per il dettaglio e il promemoria dell'esempio di stl :: transform che ha ricordato l'utilizzo di modelli per l'implementazione virtuale. –

2

Perché un operatore virtuale() non fa parte del concetto unary_function. Il concetto di funzione unaria può avere un operatore non virtuale oltre alle differenze di costanza.

Problemi correlati