Hello all,
A design question that came up during the hackathon held during the last Berlin
D Meetup.
I was trying to come up with a range that can be copied by value, but when this
is done, destroys the original handle. The idea would be behaviour something
like this:
auto originalRange = myWeirdRange(whatever);
originalRange.take(10).writeln;
assert(originalRange.empty,
"The original handle points to an empty range after copy-by-value.");
A very minimal prototype (missing out the details of front and popFront as
irrelevant) would be something like:
struct MyWeirdRange (R)
if (isInputRange!R)
{
private:
R* input_; // Assumed to never be empty, FWIW. I'm missing out
// a template check on that for brevity's sake.
public:
this (return ref R input)
{
/* return ref should guarantee the pointer
* is safe for the lifetime of the struct,
* right ... ?
*/
this.input_ = &input;
}
bool empty () @property
{
return this.input_ is null;
}
auto front () @property { ... }
void popFront () { ... }
void opAssign (ref typeof(this) that)
{
/* copy the internal pointer, then
* set that of the original to null
*/
this.input_ = that.input_;
that.input_ = null;
}
}
Basically, this is a range that would actively enforce the principle that its
use is a one-shot. You copy it by value (whether by direct assignment or by
passing it to another function), you leave the original handle an empty range.
However, the above doesn't work; even in the event of a direct assignment, i.e.
newRange = originalRange;
... the opAssign is never called. I presume this is because of the
ref-parameter input, but it's not obvious to me according to the description
here why this should be: http://dlang.org/operatoroverloading.html#assignment
Can anyone clarify what's going on here?
Anyway, my main question is: is this design idea even feasible in principle, or
just a bad idea from the get-go? And if feasible -- how would I go about it?
Thanks & best wishes,
-- Joe