Created attachment 1306
Sample file from dpaste
In situations such as the attached, std.algorithm.remove produces a
compile-time error when used on an object that fulfills its requirements only
because of `alias this`.
Issue was traced to this commit:
https://github.com/D-Programming-Language/phobos/pull/1162/files
Comment #1 by msoucy — 2013-12-27T11:30:49Z
It seems that this affects more than just std.algorithm.remove - reverse also causes compile errors, possibly others.
Comment #2 by monarchdodra — 2014-01-02T05:26:12Z
> In situations such as the attached, std.algorithm.remove produces a
compile-time error when used on an object that fulfills its requirements only
because of `alias this`.
Technically, "remove" does not produce a compile time error, because the object does *not* fulfill the requirements, and the compiler finds no adequate match.
remove (and reverse) require input to be at *least* a forward range. Foo is *not* a forward range because the type returned by `foo.save` is not `Foo`, it's an int[].
This violates the requirement that you can do this with a forward range:
Foo f;
f = f.save; //Fails
--------
The two workarounds are:
1) Pass an explicit f.bar
2) Improve Foo to be an actual forward range: give it its own "save" primitive, as well as the slicing primitives (for hasSlicing).
Also, don't forget to *re*-assign the result of "remove" after calling it, or you'll just observe "shuffled" elements.
//----
import std.stdio;
import std.algorithm;
import std.range;
struct Foo {
int[] bar;
alias bar this;
inout(Foo) save() @property inout
{
return this;
}
inout(Foo) opSlice(size_t i, size_t j) @property inout
{
return inout(Foo)(bar[i .. j]);
}
}
void main()
{
Foo f;
static assert(isRandomAccessRange!Foo);
static assert(hasSlicing!Foo);
f = [1,3,5,7,9];
(f = remove(f, 0)).writeln();
(f.bar = remove(f.bar, 0)).writeln();
(f = remove(f, 0)).writeln();
(f.bar = remove(f.bar, 0)).writeln();
}
//----