Konstruktor obiektu std::function
wymaga, aby przekazany obiekt funkcji był CopyConstructible
, ale nie jest to std::packaged_task<F>
(dla żadnego F
). std::function
wykonuje wymazanie typu , w którym typ dynamiczny nie jest widoczny w typie statycznym. Rozważmy np .:
int invoke(std::function<int()> f) { return f(); }
int main()
{
std::packaged_task<int()> p{/*etc*/};
auto l = [] { return 5; };
std::function<int()> f(/* either p or l */);
std::cout << invoke(f) << '\n';
}
Wezwanie do invoke
wymaga kopiowania f
(przechodzą przez wartość). Jednak kod f
jest kopiowalny, jeśli został wykonany z l
, ale nie można go skopiować, jeśli został wykonany z p
, a to nie ma nic wspólnego z typem statycznym f
. Istnieją zasadniczo trzy podejścia do tego problemu:
- Zakaz kopiowania
std::function
podczas kompilacji.
- Zezwalaj na kopiowanie
std::function
w czasie kompilacji, ale rzuć błąd czasu wykonywania, jeśli zawartego typu nie można skopiować.
- Umożliwia kopiowanie
std::function
w czasie kompilacji i wymaga, aby każdy obiekt funkcji, który został w nim umieszczony, był kopiowalny.
Podejście nr 1 jest bardzo restrykcyjne w zakresie sposobu przechowywania, przekazywania i udostępniania funkcji oraz w zasadzie zabrania stosowania typowych przypadków użycia na rzecz rzadkiego przypadku użycia obiektu funkcji, który nie może być kopiowany.
Podejście nr 2 jest problematyczne, ponieważ użytkownicy musieliby być wykształceni, że kopiowanie std::function
może się nie udać w niektórych przypadkach i zachować dużą staranność podczas pisania kodu. Ponadto, jeśli projekt wymaga funkcji współdzielenia, może być konieczne zapakowanie ich w postać std::shared_ptr
. A jeśli muszą być kopiowane i mogą być stanowe, staje się jeszcze gorsze.
Bez względu na to, jak postrzegasz podejście nr 3, to on został ustandaryzowany. Ale w świetle wyżej wymienionych problemów łatwo można się także bronić.
W rzeczywistości napisałem szablon klasy unique_function
, który wykorzystuje podejście nr 1 do mojego obecnego projektu, ponieważ dla nas przypadek użycia przechowywania niekopiowych asynchronicznych obiektów zadań jest dość powszechny, a kopiowanie lub udostępnianie takiego zadanie nie jest konieczne.
[Jak przechowywać niezadowalną funkcję std :: do pojemnika?] (/ Questions/28208948/how-to-store-non-copyable-stdfunction-into-a-container) – cpplearner
@cpplearner thanks, so it wszystko sprowadza się do funkcji dyktującej CopyConstructable? – xtofl