Qualifier parameters (inout on steroids)

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Thu Sep 29 06:23:55 PDT 2016


On 9/29/16 8:53 AM, Tomer Filiba wrote:
> `inout` is a useful feature, but it's nearly impossible to actually use
> it. Suppose I have
>
> struct MyTable {
>     @property items() inout {
>         return Range(&this);
>     }
>
>     static struct Range {
>         MyTable* table; // can't be inout
>     }
> }
>
> I want my items-range to be const if `this` is const or modifiable if
> `this` is modifiable.

Yes, this is a problem -- but not with inout. This is a problem with the 
lack of tail modifier syntax.

Observe how this works if Range is really a dynamic array:

@property inout(T)[] items() inout {
     return theItems; // a dynamic array
}

Works just fine. What we need is a way to say tailinout(Range), which 
means that the table member is mutable, but points at inout data.

> I ended up with
>
>     @property items() {
>         return Range!false(&this);
>     }
>     @property items() const {
>         return Range!true(&this);
>     }

There is a way to make this more DRY, but it is still ugly, and loses 
the benefits of inout. You need to use template this parameters:

struct Range(T)
{
    T *table;
}

@property items(this T)() {
     return Range!T(&this);
}

> It would be really nice if I could "capture" the qualifiers and be
> parameterized on them as well. For example,
>
> int opApply(qual Q)(scope int delegate(int x) Q dg) Q;

I once thought this would work well, but in practice I think it would be 
a disaster. Imagine everyone defining their own set of qualifiers and 
how they will work.

It's also a template, and does not protect against modification of 
mutable data, or static if to change layout/implementation/etc.

I am working on an article to propose a tail modifier syntax. This would 
solve most of these problems.

-Steve


More information about the Digitalmars-d mailing list