2016-07-13 69 views
8

In discussione avevamo here Stavo giocando con i funtori che passavano. C++ STL passa funtori come valori (visto in std::for_each, std::find_if, std::transform)Perché il functor basato su modelli è passato come valore e non ha inoltrato il riferimento

Così dichiarando miniera sarebbe come questo.

template<typename F> 
void call_me(F f) 
{ 
    f(); 
} 

Ora, chiamando probabilmente potrebbe invocare ftor 's costruttore di copia (che molto probabilmente sarà la copia eliso, quindi non è il caso). Ma ftor f{}; call_me(f); provocherà la copia. Se ftor ha grandi dati, potrebbe essere un problema.

Lo miglioreremo passandolo come riferimento const (void call_me(const F& f)) per eliminare la copia non necessaria. Questo va bene finchè ftor::operator() è const. In caso contrario, la chiamata a call_me comporterebbe un errore di compilazione (perdita di qualificatori const).

Quindi, perché preoccuparsi di riferimento const, utilizzare solo riferimento (void call_me(F& f)). Questo va bene, ma non funzionerebbe perché il primo caso fosse poiché il binsing del valore r su (non-const) il riferimento al valore-l non è valido.

Dichiarare f come riferimento di inoltro (void call_me(F&& f)) sembra funzionare in tutti i casi. Credo che questo funzioni grazie al riferimento al collasso.

Quindi, perché i funtori basati su modelli non vengono inoltrati come riferimenti di inoltro nelle funzioni da STL?

risposta

9

perché i funtori basati su modelli non vengono passati come riferimenti di valore r nelle funzioni da STL?

Prima di tutto, sarebbero spedizione riferimenti, non riferimenti rvalue.

Detto questo, come per molte "perché" domande sulla progettazione della lingua in generale, la risposta può essere semplicemente: perché nessuno ha ancora proposto questa modifica (vedere how to submit a proposal). Sospetto che una grande quantità di oggetti funzione passati negli algoritmi di libreria standard siano o lambda, apolidi o estremamente economici. Inoltre, se si dispone di un oggetto così costoso si può sempre rivolgersi al suo interno in un uno a buon mercato copiabile ai fini dell'algoritmo:

call_me(std::ref(huge_object)); 

Infine, alcuni di questi algoritmi si basano su passaggio di queste funzioni oggetti intorno ad altri soccorritori . Se l'algoritmo presuppone semplicemente che l'oggetto funzione sia "libero" da copiare, è facile codificarlo. Se introduciamo qui la possibilità di rvalues, questo aggiunge un altro strato di domande che devono essere affrontate - passiamo semplicemente il riferimento in giro? Per quanto riguarda gli oggetti funzione con qualifica ref operator()?

Alcuni combinazione di quanto sopra probabilmente spiega perché, per esempio, è ancora:

template <class InputIt, class UnaryPredicate> 
InputIt find_if(InputIt, InputIt, UnaryPredicate); 

e non

template <class InputIt, class UnaryPredicate> 
InputIt find_if(InputIt, InputIt, UnaryPredicate&&); 
Problemi correlati