Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is std::for_each a non-modifying sequence operation?

I just read in the C++ standard that std::for_each is a non-modifying sequence operation, along with find, search and so on. Does that mean that the function applied to each element should not modify them? Why is that? What could possibly go wrong?

Here is a sample code, where the sequence is modified. Can you see anything wrong with it?

void foo(int & i)
{
    i = 12;
}

int main()
{
    std::vector<int> v;
    v.push_back(0);

    std::for_each(v.begin(), v.end(), foo);
    // v now contains 12
}

I suspect this to be just an interpretation issue, but I wanted to have your opinion about that.

PS: I know I could use std::transform instead of for_each, but that's not the point.

like image 511
Luc Touraille Avatar asked Mar 19 '09 16:03

Luc Touraille


3 Answers

Quite simply, you can't make a change that could modify the structure of the container. That's because in the general case, modifying a container can invalidate the iterators being used.

You can modify the element as long as it doesn't change the container's structure (such as the order of elements in the container).

[addition]


Note that there seems to be some confusion about for_each being a 'non-modifying' algorithm. This confusing situation is summed up here by Stroustrup in errata for the 4rd Printing of "The C++ Programming Language, 3rd Ed." (CPL) has this to say about whether for_each can modify the elements of a sequence (http://www.research.att.com/~bs/3rd_printing5.html):

"The for_each() algorithm is classified as nonmodifying because it doesn't explicitly modify a sequence. However, if applied to a non-const sequence for_each() may change the elements of the sequence. For an example, see the use of negate() in 11.9." (recent standards resolution).

The CPL originally indicated that the function or function object passed to for_each was not permitted to modify the element passed to it. However, the CPL was written and originally published before the standard was finalized, and apparently this restriction on for_each() was removed before it was finalized.

See also:

  • http://www.angelikalanger.com/Articles/Cuj/03.ForeachTransform/ForEachTransform.html
  • the C++ LWG defect report mentioned in litb's answer (http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#475)
like image 88
Michael Burr Avatar answered Nov 15 '22 10:11

Michael Burr


See this defect report they say

The LWG believes that nothing in the standard prohibits function objects that modify the sequence elements. The problem is that for_each is in a secion entitled "nonmutating algorithms", and the title may be confusing. A nonnormative note should clarify that.

But also note this one.

They seem to call it "non-modifying" because for_each itself does not exlicitly modify the elements of the sequence.

like image 27
Johannes Schaub - litb Avatar answered Nov 15 '22 11:11

Johannes Schaub - litb


I think "Non-modifying sequence operations" mean that this operation not modify sequence. But operation could modify container elements.

Value of container elements and sequence - different things.

like image 6
bayda Avatar answered Nov 15 '22 11:11

bayda