I don't think this whole issue has anything to do with ranges. I think this is an issue of assuming that the symbol = means "copy what's on the right to what's on the left". When in reality, = could mean: (if what's on the right has reference semantics) "make what's on the left reference the same thing that the thing on the right references".

I think all range types should be allowed to return whatever they want from their front property. It's the responsibility of the user of the range to *actually* copy what front returns (if that's what he intends), instead of assuming that = means copy.

In the code below, X marks the bug:

module main;

import std.stdio;
import std.range;

class MyData
{
    int _value;
}

struct MyFwdRange
{
    MyData _myData;

    this(MyData md)
    {
        _myData = md;
    }

    @property MyData front()
    {
        return _myData;
    }

    @property bool empty() const
    {
        return _myData._value > 10;
    }

    void popFront()
    {
        _myData._value++;
    }

    @property MyFwdRange save() const
    {
        auto copy = MyFwdRange();
        copy._myData = new MyData();
        copy._myData._value = _myData._value;
        return copy;
    }
}

void printFirstAndSecond(R)(R range)
    if (isForwardRange!MyFwdRange)
{
    //         X
    auto first = range.front; // That is *not* copying

    range.popFront();
    writeln(first._value, " ", range.front._value);
}

void main()
{
    auto mfr = MyFwdRange(new MyData());

    printFirstAndSecond(mfr); // prints: 1 1 (instead of 0 1)
}

Reply via email to