On 9/17/2010 3:08 AM, Andrei Alexandrescu wrote:
So the crux of the matter is not operating on constant ranges (which I believe we can safely drop), but obtaining non-constant ranges from constant containers.

I agree we need to drop operating on constant ranges for the general case, but I think it's trivial to fix for a lot of common cases by just adding Unqual. This would fix arrays, iota and everything else that has a "natural" tail const.


The idea that we could use a symbolic name for the qualifier is, I think, workable, but Walter has resisted it on account of exacerbated complexity in the implementation. We should explore other means for the time being.

Right now a typical container implementation goes like this:

struct Container(T)
{
    ...
    struct Range { ... }
    Range opSlice() { ... }
}

A container might define several ranges, but c[] yields the container's primary, most prominent range. Now if we have a const Container!Widget object, we need to find an idiomatic way to extract a range from it. Here's some code that compiles and runs as expected:

#!/bin/env rdmd
import std.stdio;

struct Container(T)
{
    static struct Node { T payload; Node * next; }
    Node * root;
    struct Range(N) {
        private N * n;
        @property T front() { return n.payload; }
        @property bool empty() { return n is null; }
        void popFront() { n = n.next; }
    }
    Range!Node opSlice() {
        return typeof(return)(root);
    }
    Range!(const Node) opSlice() const {
        return typeof(return)(root);
    }
}

void main() {
    Container!int c1;
    c1.root = new c1.Node;
    c1.root.payload = 5;
    c1.root.next = new c1.Node;
    c1.root.next.payload = 7;
    foreach (i; c1[]) writeln(i);

    foo(c1);
}

void foo(const Container!int c1) {
    foreach (i; c1[]) writeln(i);
}

The basic idea is that the qualifier is propagated from the container to the range together with the type of the representation held inside the range.

This would solve the case where the range and the container are truly distinct animals, but in a lot of cases they aren't.

I'm not sure how generalizable this is, but it's a start. There is also the remaining nagging issue of duplicating the line

        return typeof(return)(root);

which in other cases might expand to more lines.

Shouldn't inout solve this once it's fully implemented? Or maybe template this parameters + auto return types?

Range!(inout Node) opSlice() inout {
     return typeof(return)(root);
}

or

auto opSlice(this This)() {
    return Range!(typeof(root))(root);
}


_______________________________________________
phobos mailing list
[email protected]
http://lists.puremagic.com/mailman/listinfo/phobos

Reply via email to