9

この投稿では、回答の 1 つがstd::stringケースを次のように変更することを推奨しています。

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

私はそれを使用しており、これまでのところ Visual Studio 2010 で動作します。しかし、標準では常に動作することが保証されていますか? 私の懸念は、出力反復子 (3 番目の引数) への書き込みが入力反復子 (引数 1 と 2) を無効にする実装の可能性を想像できることです。

要約すると、上記の方法は安全で移植可能ですか?

4

3 に答える 3

11

Yes, this is guaranteed to be safe (as long as operation itself doesn't modify the elements or invalidate iterators).
From 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 Requires: op and binary_op shall not invalidate iterators or subranges, or modify elements in the ranges [first1,last1], [first2,first2 + (last1 - first1)], and [result,result + (last1 -first1)].

[...]

5 Remarks: result may be equal to first in case of unary transform, or to first1 or first2 in case of binary transform.

于 2013-10-05T17:43:41.240 に答える
3

の最初の可能な実装を調べると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;
}

「安全」ではないように見えるかもしれません。

ただし、std::transform(str.begin(), str.end(),str.begin(), ::toupper);

d_firstfirst1同じ場所を指していますが、それらは同じイテレータではありません!

1 つのステートメントで両方のイテレータをインクリメントしても問題はありません。

別の実装は、(MingW ヘッダー ファイルから) このようなもので、同等ですが、少しきれいに見えます。

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;
}

John Bartholomew のおかげで編集

于 2013-10-05T17:40:06.467 に答える
2

はい、入力イテレータを出力イテレータとしても使用できます。変更アルゴリズムでは、他の宛先コンテナではなく、(ソース コンテナで) インラインで変更が行われることを意味します。

于 2013-10-05T17:44:20.803 に答える