Cppreference ma ten przykładowy kod dla std::transform
:
std::vector<std::size_t> ordinals;
std::transform(s.begin(), s.end(), std::back_inserter(ordinals),
[](unsigned char c) -> std::size_t { return c; });
Ale mówi również:
std::transform
nie gwarantuje zastosowaniaunary_op
lubbinary_op
. Aby zastosować funkcję do sekwencji w kolejności lub zastosować funkcję, która modyfikuje elementy sekwencji, użyjstd::for_each
.
Ma to prawdopodobnie umożliwić równoległe wdrożenia. Jednak trzecim parametrem std::transform
jest LegacyOutputIterator
następujący warunek ++r
:
Po tej operacji
r
nie wymaga się, aby była inkrementowalna, a wszelkie kopie poprzedniej wartościr
nie muszą już być dereferencyjne ani inkrementowalne.
Wydaje mi się więc, że przyporządkowanie danych wyjściowych musi nastąpić po kolei. Czy oznaczają one po prostu, że aplikacja unary_op
może być nieczynna i przechowywana w tymczasowej lokalizacji, ale kopiowana na wyjście w odpowiedniej kolejności? To nie brzmi jak coś, co kiedykolwiek chciałbyś zrobić.
Większość bibliotek C ++ nie zaimplementowało jeszcze równoległych programów wykonawczych, ale Microsoft ma. Jestem prawie pewien, że jest to odpowiedni kod i myślę, że wywołuje tę populate()
funkcję, aby rejestrować iteratory w porcjach danych wyjściowych, co z pewnością nie jest prawidłową rzeczą, ponieważ LegacyOutputIterator
może zostać unieważnione przez zwiększenie jej kopii.
czego mi brakuje?
s
, co unieważnia iteratory.
std::transform
z zasad exaction, wymagany jest iterator o dostępie swobodnym, który back_inserter
nie może spełnić. Cytowana przez IMO dokumentacja części odnosi się do tego scenariusza. Uwaga przykład w zastosowaniach dokumentacji std::back_inserter
.
transform
wersją, która decyduje, czy użyć paralelizmu. Wtransform
przypadku dużych wektorów zawodzi.