Exceptional coding style

monarch_dodra monarchdodra at gmail.com
Tue Jan 15 14:10:22 PST 2013


On Tuesday, 15 January 2013 at 21:26:14 UTC, Stewart Gordon wrote:
> On 15/01/2013 10:20, FG wrote:
> <snip>
>> All thanks to a terrible naming decision...
>> It's not remove but move_to_end. Why call it remove?

It HAS to do this because there is a separation of iteration 
primitives and container. An iterator cannot (by itself) 
spontaneously remove a value from a container.

FWI, D has the EXACT same semantics:
1) Use std.algorithm.remove to bump the unwanted values to the 
end of the range, receiving in return a range of said elements.
2) Pass said range to std.container.remove to remove(erase) the 
elements from the container itself.

It may not be intuitive at first, but it makes perfect sense, and 
is (very) good design. It keeps orthogonal concepts orthogonal. 
the erase remove idiom always surprises the first time around, 
but quickly becomes natural. It's a tried and tested idiom.

> It doesn't necessarily move them to the end, going by
> http://www.cplusplus.com/reference/algorithm/remove/
> "The relative order of the elements not removed is preserved, 
> while the elements past the new end of range are still valid, 
> although with unspecified values."
>
> Just looking at the sample implementation there....
>
>     if (!(*first == value)) *result++ = *first;
>
> places each non-removed value in its place in the final state 
> of the container, but doesn't do anything particular with the 
> value where it was taken from.  In a C++11 implementation, I 
> would expect it to become
>
>     if (!(*first == value)) *result++ = std::move(*first);
>
> Stewart.

Note that: "The behavior of this function template is *equivalent 
to*"

In no way does this mean this is the actual implementation. 
Besides, the actual definition as decribed in n3242 is:
//----
Requires: The type of *first shall satisfy the MoveAssignable 
requirements

Effects: Eliminates all the elements referred to by iterator i in 
the range [first,last) for which the following corresponding 
conditions hold: *i == value, pred(*i) != false.

Returns: The end of the resulting range.
//----

The "MoveAssignable" implies what you just said.


More information about the Digitalmars-d mailing list