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.
Grazie per il dettaglio e il promemoria dell'esempio di stl :: transform che ha ricordato l'utilizzo di modelli per l'implementazione virtuale. –