2016-02-14 10 views
6

Rozważmy następujący fragment kodu:boost :: function_output_iterator zbudowane z funkcji lambda nie jest przypisane

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! 

Problem polega na tym, function_output_iterator skonstruowane w ten sposób nie jest przypisane, a tym samym nie spełnia pojęcie Iterator, który wymaga typu: CopyAssignable.

To nie jest błąd, ponieważ boost Function Output Iterator documentation wyraźnie says:

UnaryFunction musi być przypisania i Kopiuj konstruowalnych.

ile operator przypisanie lambda function zostanie usunięty:

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

Więc to zachowanie jest technicznie poprawne, ale dla mnie jest dość nieoczekiwane. Myślę, że jest to całkowicie uzasadnione pragnienie skonstruowania function_output_iterator, biorąc pod uwagę zamknięcie wytwarzane przez funkcję lambda. Wydaje mi się niewygodne, dlaczego ten przypadek użycia powoduje problem.

Hm, ok, ten StackOverflow, więc muszę zadać pytanie :) Oto, jak to obejść? Jak uzyskać poprawny iterator, biorąc pod uwagę zamknięcie, które działa jak function_output_iterator?

I kolejna: czy warto przygotować propozycję lub raport o błędzie, aby go zwiększyć?

+2

Działa, jeśli używasz 'std :: function' zamiast' auto': http://coliru.stacked-crooked.com/a/0e92b2ce686b4dff – jrok

+3

Kolejna alternatywa, jeśli nie musisz niczego przechwytywać: http: //coliru.stacked-crooked.com/a/41d7a423016c38e7 – llonesmiz

+0

@jrok dobry komentarz, powinien być odpowiedzią. – Mikhail

Odpowiedz

5

Wystarczy zapisać zamknięcie w std::function:

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

Test snippet.

7

inną opcją, jeśli jesteś pewien, że zamknięcie przeżyje iteracyjnej i jego kopie, owinąć go std::ref:

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

Demo.

A oto propozycja dla klasy użytkowej doładowania ustalające ten szczególny problem: boost::regular

zobaczyć odpowiednią dyskusję w boost mailing list.

Powiązane problemy