Is it safe to input the iterator and output the iterator to std :: transform from one container?

In this post, one of the answers recommends changing the std::string case to std::string like this:

 std::string str = "Hello World"; std::transform(str.begin(), str.end(),str.begin(), ::toupper); 

I used it, and it still works in Visual Studio 2010. But is it guaranteed that the standard always works? What bothers me is that I can imagine implementation possibilities when writing to the output iterator (third argument) can invalidate the input iterators (arguments one and two).

So, in general, is the above method safe and portable?

+6
source share
3 answers

Yes, this is guaranteed to be safe (until the operation itself modifies the elements or cancels the iterators).
From the chapter [alg.transform] from draft n3337:

 template<class InputIterator, class OutputIterator, class UnaryOperation> OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op); template<class InputIterator1, class InputIterator2, class OutputIterator, class BinaryOperation> OutputIterator transform(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryOperation binary_op); 

2 Required: op and binary_op must not invalidate iterators or subranges or change elements to the ranges [first1,last1] , [first2,first2 + (last1 - first1)] and [result,result + (last1 -first1)] .

[...]

5 Notes: result may be equal to first in the case of a unary conversion, or in first1 or first2 in the case of a binary conversion.

+9
source

If you look at the first possible implementation of std::transform

 template<class InputIt, class OutputIt, class UnaryOperation> OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op) { while (first1 != last1) { *d_first++ = unary_op(*first1++); } return d_first; } 

This may not seem to be "safe."

However, with std::transform(str.begin(), str.end(),str.begin(), ::toupper);

d_first and first1 point to the same place, but this is not the same iterator!

There is no problem adding both of these iterators to a single statement.

Another implementation is something like this (from the MingW header file), which is equivalent but looks cleaner

 template<class InputIt, class OutputIt, class UnaryOperation> OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op) { for (; first1 != last1; ++first1, ++d_first) *d_first = unary_op(*first1); return d_first; } 

Edited by John Bartholomew

+3
source

Yes, you can use the input iterator as the output iterator, and in the modification algorithm this means that the modification will be performed inline (in the source container), and not in another destination container.

+2
source

Source: https://habr.com/ru/post/955308/


All Articles