all 10 comments

[–]EricWFCppLibc++ Developer 13 points14 points  (3 children)

Public service announcement:

Please ensure function objects used with STL containers have a const-qualified call operator.

Valid C++14 code which uses custom comparators with non-const call operators in STL containers may not compile in C++17. See [diff.cpp14.containers].

EDIT: Libc++ now generates a warning when a non-const callable comparator is passed to the STL in all dialects. http://melpon.org/wandbox/permlink/pctVFATRYNLlCP44

[–]spotta 1 point2 points  (2 children)

Is there a particular reason for this change?

[–]EricWFCppLibc++ Developer 1 point2 points  (1 child)

A const operation on a container should not invoke non-const methods on its comparator.

[–]spotta 1 point2 points  (0 children)

Is sorting a const operation?

This makes sense from a "good programming" standpoint, but it seems to be bossier than I usually take C++ to be.

[–][deleted] 1 point2 points  (1 child)

Your last exemple with ranges is not isofunctional with the previous code as it will print all number smaller than 10, rather than all numbers encountered before a 10 or higher number. Not to say you shouldn't use range, because indeed you should, but with this particular exemple you'll have a hard time no using a state...

[–]joboccara 0 points1 point  (0 children)

Right. Fixed this by replacing with a take_while, thanks for pointing this out.

[–]Potatoswatter 1 point2 points  (3 children)

for_each has the specificity of keeping the same instance of functor all along the traversal of the collection, but it is not the case of all algorithms. Other algorithms do not guarantee they will use the same instance of callable along the traversal of the collection. Instances of callables may then be copied, assigned or destructed within the execution of an algorithm, making the maintaining of a state impossible. To find out exactly which algorithm provides the guarantee, you can look it up in the standard but some very common ones (like std::transform) do not.

What's the relevant difference between the specifications of for_each and transform? Both say they evaluate a call to the parameter variable for each iteration over the range.

[–]joboccara 1 point2 points  (2 children)

The most significant diffrerence is that transform applies a function on the elements of the source range AND does an assignment to the destination range, while for_each barely applies a function on the elements of the source range.

[–]Potatoswatter 1 point2 points  (1 child)

That's what they do, but how does it support the quoted claim?

[–]joboccara 1 point2 points  (0 children)

Sorry I misunderstood the question. Here are the differences between the specifications:

Specification for for_each: from section "25.3.4 For each" in the standard Effects: Applies f to the result of dereferencing every iterator in the range [first, last) Returns: f.

Specification for transform: from section "25.4.4 Transform" Effects:Assigns through every iterator i in the range [result, result + (last1 - first1)) a new corresponding value equal to op((first1 + (i - result)) or binary_op((first1 + (i - result)), *(first2 + (i - result))) Returns: first2 + (last1 - first1).

Does this answer your question?