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