Cppreference possui este código de exemplo para 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; });
Mas também diz:
std::transform
não garante a aplicação em ordem deunary_op
oubinary_op
. Para aplicar uma função a uma sequência em ordem ou para aplicar uma função que modifica os elementos de uma sequência, usestd::for_each
.
Presumivelmente, isso permite implementações paralelas. No entanto, o terceiro parâmetro de std::transform
é um LegacyOutputIterator
que possui a seguinte pós-condição para ++r
:
Após esta operação,
r
não é necessário incrementar e nenhuma cópia do valor anterior der
não é mais necessária para ser desreferenciável ou incrementável.
Portanto, parece-me que a atribuição da saída deve ocorrer em ordem. Eles simplesmente significam que a aplicação de unary_op
pode estar fora de ordem e armazenada em um local temporário, mas copiada na saída em ordem? Isso não soa como algo que você gostaria de fazer.
A maioria das bibliotecas C ++ ainda não implementou executores paralelos, mas a Microsoft implementou. Tenho certeza de que esse é o código relevante e acho que ele chama essa populate()
função para gravar iteradores em partes da saída, o que certamente não é uma coisa válida a ser feita, porque LegacyOutputIterator
pode ser invalidada pelo aumento de cópias dele.
o que estou perdendo?
s
que invalida os iteradores.
std::transform
com a política de exação, será necessário um iterador de acesso aleatório que back_inserter
não pode ser cumprido. A documentação da peça citada pela IMO refere-se a esse cenário. Observe o exemplo nos usos da documentação std::back_inserter
.
transform
versão que decide se deve ou não usar paralelismo. Otransform
para vetores grandes falha.