Boost logo

Boost :

From: Jaakko Jarvi (jajarvi_at_[hidden])
Date: 2004-05-21 14:25:43


On May 21, 2004, at 11:50 AM, Stephan T. Lavavej wrote:

> [Jaakko Jarvi]
>> I'm reading the standard back and forth and I do not agree
>> with you.
>
> The Standard is not very well written when it comes to this point, yes.
> However, I am right, and in the course of this E-mail, you will be
> convinced
> that I am right. :->
>
>> What do you mean by "inherently mutating sequences"?
>
> Algorithms which always modify the sequences that they are given.

>> Does std::replace inherently modidfy sequences?
>
> Yes, because its purpose is to write NewValue in every place that
> OldValue
> occurs.
>

I'm reading more from the standard, and getting more confused...

All other algorithms in the non-modifying category either take
a Predicate argument, (which is specified to not call any non-const
function through the dereferenced iterator) or perform equality
comparisons. for_each is the only one that takes a 'free-form' function
object.

If side effects are allowed, I don't understand why for_each is
classified as a non-modifying sequence. It sure can modify the elements
of the sequence. What is (philosophically) different in the way
that, say, std::replace, modifies the elements of the sequence?

Compare these:

std::replace(a.begin(), a.end(), 1, 2);
std::for_each(a.begin(), a.end(), boost::lambda::if_then(_1 == 1, _1 =
2));

Regarding Langer's paper, I'm not convinced that the standard can,
at the moment, be interpreted in that way. I'm convinced that the
description
is ambiguous. Maybe for_each should be just moved to mutating sequence
operators.

>
> If you are still unconvinced, see Library DR 290, where Angelika Langer
> (coauthor of the above article) complains that there are insufficient
> restrictions on for_each's functor. Note that she asks that the
> functor be
> required to not invalidate iterators or subranges. The DR is still
> open,
> but note that the LWG's response so far is "we think this should be a
> blanket statement", not "what are you talking about, for_each's functor
> cannot mutate its argument period, much less invalidate iterators".

I read LWG's response as it says, it should be a blanket statement for
all algorithms.

>
> Finally: http://www.research.att.com/~bs/3rd_printing5.html
>
> "pg 524 add at the end of the page: "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)."
>

Do you know what Bjarne is referring to with the 'recent standards
resolution'?

The sgi STL documentation (predecessor of what is currently in the
standard) says:

   UnaryFunction does not apply any non-constant operation through its
argument.

UnaryFunction refers to the type of the function object to for_each.
Here's the relevant
link:

   http://www.sgi.com/tech/stl/for_each.html

This must be the initial reason why for_each is in the category of
non-modifying sequences.
the categorization came from Stepanov et al., but the requirements did
not follow unchanged.

In sum, I think the footnote is justified (I don't believe I'm putting
this much
mental energy to justifying a presence of a footnote :), at least until
the standard
is clarified. A DR would be in place: either explicitly mention that
side-effects
(of the sort that modify the values in the sequence) are not allowed,
or move
for_each to mutating algs. Volunteer to raise that and provide wording?

   Best, Jaakko


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk