When I work with my favorite containers, I tend to chain operations. For instance, in the well-known Erase–remove idiom:
v.erase( std::remove_if(v.begin(), v.end(), is_odd), v.end() );
From what I know of the order of evaluation, v.end()
(on the rhs) might be evaluated before the call to std::remove_if
. This is not a problem here since std::remove*
only shuffle the vector without changing its end iterator.
But it could lead to really surprising constructs, like for instance (demo):
#include <iostream>
struct Data
{
int v;
int value() const { return v; }
};
auto inc(Data& data) { return ++data.v; }
void print_rhs(int, int value) { std::cout << value << '\n'; }
int main()
{
Data data{0};
print_rhs(inc(data), data.value()); // might print 0
}
This is surprising since print_rhs
is called after inc
has been called; which means data.v
is 1
when print_rhs
is called. Nevertheless, since data.value()
might be evaluated before, 0
is a possible output.
I think it might be a nice improvement if the order of evaluation would be less surprising; in particular if the arguments of a function with side effects were evaluated before those without.
My questions are then:
- Has that change ever been discussed or suggested in a C++ committee?
- Do you see any problem it could bring?