Cppreference có mã ví dụ này cho 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; });
Nhưng nó cũng nói:
std::transform
không đảm bảo ứng dụng theo thứ tự củaunary_op
hoặcbinary_op
. Để áp dụng một chức năng cho một thứ tự theo thứ tự hoặc để áp dụng một chức năng sửa đổi các yếu tố của một chuỗi, sử dụngstd::for_each
.
Điều này có lẽ là để cho phép thực hiện song song. Tuy nhiên, tham số thứ ba của std::transform
là một LegacyOutputIterator
trong đó có các điều kiện sau cho ++r
:
Sau thao tác
r
này không bắt buộc phải tăng lên và bất kỳ bản sao nào của giá trị trước đór
không còn được yêu cầu để có thể hủy bỏ hoặc tăng thêm.
Vì vậy, dường như việc gán đầu ra phải diễn ra theo thứ tự. Có phải chúng chỉ đơn giản có nghĩa là ứng dụng unary_op
có thể bị lỗi và được lưu trữ đến một vị trí tạm thời, nhưng được sao chép vào đầu ra theo thứ tự? Điều đó không giống như những gì bạn muốn làm.
Hầu hết các thư viện C ++ chưa thực sự triển khai các trình thực thi song song, nhưng Microsoft thì có. Tôi khá chắc chắn đây là mã có liên quan và tôi nghĩ rằng nó gọi hàm nàypopulate()
để ghi lại các vòng lặp thành khối của đầu ra, điều này chắc chắn không phải là điều hợp lệ để làm vì LegacyOutputIterator
có thể bị vô hiệu hóa bằng cách tăng các bản sao của nó.
Tôi đang thiếu gì?
s
, điều này làm mất hiệu lực các trình vòng lặp.
std::transform
với chính sách đòi hỏi quá đáng rồi truy cập ngẫu nhiên iterator là cần thiết mà back_inserter
không thể thực hiện. IMO trích dẫn một phần tài liệu đề cập đến kịch bản đó. Lưu ý ví dụ trong tài liệu sử dụng std::back_inserter
.
transform
phiên bản quyết định có sử dụng paralelism hay không. Cáctransform
vectơ lớn thất bại.