Cppreference ha questo codice di esempio per 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; });
Ma dice anche:
std::transform
non garantisce l'applicazione in ordine diunary_op
obinary_op
. Per applicare una funzione a una sequenza in ordine o per applicare una funzione che modifica gli elementi di una sequenza, utilizzarestd::for_each
.
Ciò è presumibilmente per consentire implementazioni parallele. Tuttavia, il terzo parametro di std::transform
è a LegacyOutputIterator
che ha la seguente postcondizione per ++r
:
Dopo questa operazione
r
non è necessario essere incrementabili e le copie del valore precedente dir
non devono più essere dichiarabili o incrementabili.
Quindi mi sembra che l'assegnazione dell'output debba avvenire in ordine. Significa semplicemente che l'applicazione di unary_op
potrebbe essere fuori servizio e archiviata in una posizione temporanea, ma copiata nell'output in ordine? Non sembra qualcosa che vorresti mai fare.
La maggior parte delle librerie C ++ non ha ancora implementato gli esecutori paralleli, ma Microsoft ha. Sono abbastanza sicuro che questo sia il codice pertinente e penso che chiama questa populate()
funzione per registrare iteratori in blocchi dell'output, che sicuramente non è una cosa valida da fare perché LegacyOutputIterator
può essere invalidato incrementandone le copie.
Cosa mi sto perdendo?
s
, il che invalida gli iteratori.
std::transform
con criteri di esazione, è necessario un iteratore ad accesso casuale che back_inserter
non può essere eseguito. La documentazione della parte quotata IMO si riferisce a quello scenario. Nota esempio nell'uso della documentazione std::back_inserter
.
transform
versione che decide se usare o meno il paralelismo. Iltransform
per vettori di grandi dimensioni ha esito negativo.