[Issue 19981] std.algorithm.iteration.group fails when element type has a const/immutable member

d-bugmail at puremagic.com d-bugmail at puremagic.com
Tue Jun 18 19:51:03 UTC 2019


https://issues.dlang.org/show_bug.cgi?id=19981

--- Comment #1 from Vladimir Panteleev <dlang-bugzilla at thecybershadow.net> ---
It doesn't work because Group.front's return value is a ref to a field
(_current), however, because the range element type has const members, it
cannot be overwritten, i.e. it would break:

auto r=group(...);
auto p = &r.front.x;
auto v = *p; r.popFront;
assert(*p == v, "A const variable has changed");`.

It's not actually a problem from this side with const, but it is with
immutable, which exhibits the same issue.

Not sure this is fixable in the general case, since many range algorithms have
to store a copy of the range elements in some way. Adding constness to field
members implies restricting some operations on them.

This could be worked around by wrapping the actual values with a proxy type
which stores a pointer but forwards everything else to the pointer target
(perhaps something like this exists in Phobos already):

////////////////////////////////// test.d //////////////////////////////////
import std.algorithm.iteration;
import std.stdio;
import std.typecons;

struct Ref(T)
{
    T* _obj;
    ref inout(T) getObj() inout { return *_obj; }
    alias getObj this;

    bool opEquals(ref Ref other) const { return *other._obj == *this._obj; }
}
Ref!T toRef(T)(ref T v) { return Ref!T(&v); }

void main()
{
    static struct X {
        immutable int x;
    }
    [X(1),X(2),X(2),X(3)]
        .map!((ref x) => toRef(x))
        .group()
        .writeln();
}
////////////////////////////////////////////////////////////////////////////

--


More information about the Digitalmars-d-bugs mailing list