2016-02-14 11 views
6

Si consideri il seguente frammento di codice:boost :: function_output_iterator costruito funzione di lambda non è cedibile

auto f = [](int x) { std::cout << x; }; 
auto it = boost::make_function_output_iterator(f); 
decltype(it) it2 = it; // Ok, copied 
it2 = it; // Does not compile, cannot assign! 

Il problema è, function_output_iterator costruito in questo modo non è assegnabile, e quindi non soddisfa il concetto Iterator, che richiede che il tipo sia CopyAssignable.

Questo non è un bug, in quanto boost Function Output Iterator documentation chiaramente says:

UnaryFunction deve essere assegnabili e Copia Constructible.

Mentre operatore di assegnazione di un lambda function viene cancellato:

ClosureType& operator=(const ClosureType&) = delete; 

Quindi questo comportamento è tecnicamente corretta, ma per me è un po 'inaspettato. Penso che sia un desiderio perfettamente ragionevole costruire function_output_iterator dato una chiusura prodotta dalla funzione lambda. Mi sembra inopportuno il motivo per cui questo caso d'uso causa un problema.

Hm, ok, questo StackOverflow, quindi devo fare qualche domanda :) Eccolo: come risolvere questo? Come ottenere un iteratore corretto con una chiusura, che si comporta come function_output_iterator?

E un altro: vale la pena di fare una proposta o una segnalazione di bug da potenziare?

+2

Funziona se si utilizza 'std :: function' invece di' auto': http://coliru.stacked-crooked.com/a/0e92b2ce686b4dff – jrok

+3

Un'altra alternativa se non è necessario acquisire nulla: http: //coliru.stacked-crooked.com/a/41d7a423016c38e7 – llonesmiz

+0

@jrok buon commento, dovrebbe essere la risposta. – Mikhail

risposta

5

Basta salvare la chiusura in un std::function:

std::function<void(int)> f = [](int x) { std::cout << x; }; 
auto it = boost::make_function_output_iterator(f); 

Test snippet.

7

Un'altra opzione, se si è sicuri della chiusura sopravviverà l'iteratore e le sue copie, avvolgerlo con std::ref:

auto f = [](int x) { std::cout << x; }; 
auto it = boost::make_function_output_iterator(std::ref(f)); 

Demo.

Ed ecco una proposta per una classe di utilità spinta risoluzione di questo problema particolare: boost::regular

veda la discussione corrispondente boost mailing list.

Problemi correlati