Yesterday, I came across this bug that is caused by design of std.range.interfaces. The problem is that InputRange
has an abstract member function moveFront()
.
Why is this a problem, you could ask - if I'm able to get a front
of a range by copy, surely I can get it when I don't even require a copy? This is all good and true with most types. But moveFront()
from std.range.primitives
, just like core.lifetime.move
, will require the element to be a LValue. moveFront()
is smart enough to use copy with RValues if there are no copy constructors or postblits, but with them a reference access to front
is required. It follows that the dynamic range interfaces will not work at for ranges with RValue elements with copy constructors:
import std;
struct HasCC
{ inout this(ref inout typeof(this)){}
}
void main()
{ // will not compile
auto dynamicRange = repeat(HasCC.init).inputRangeObject;
}
What should we do about this? One could argue that moveFront
belongs to InputAssignable
as opposed to InputRange
, but I think it would be too much breakage to change it like that anymore.
Another option might be to say that moveFront
should behave just like front
when front
is a RValue. Either just in std.range.interfaces
or also in std.range.primitives
. Perhaps even move
could behave like that? But maybe there is some reason I'm missing why they do not act like that already?
We could also leave it just as is, documenting the limitation in std.range.interfaces
. It would not necessarily mean a permanent defeat, because of possibility to fix it in Phobos V2 (Timeline estimates on that, anyone?).