Generic operator overloading for immutable types?

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Jun 13 15:45:50 PDT 2017


On 6/13/17 5:58 PM, ag0aep6g wrote:
> On 06/13/2017 10:50 PM, Steven Schveighoffer wrote:
>> const(inout) actually *is* a thing :)
>>
>> It's a type constructor that can be implicitly cast from immutable.
>> This has advantages in some cases.
>>
>> See (horribly written) table at the bottom if the inout function
>> section here: http://dlang.org/spec/function.html#inout-functions
>>
>> Also I talked about it last year at Dconf 2016:
>> http://dconf.org/2016/talks/schveighoffer.html
>
> Huh. There it is.
>
> Took me some experimenting to understand what it does. If anyone else is
> interested, this is where it clicked for me:
>
> ----
> inout(int*) f(inout int* x, inout int* y)
> {
>     return y;
> }
>
> inout(int*) g(inout int* x)
> {
>     immutable int* y;
>     return f(x, y); /* Error: cannot implicitly convert expression f(x,
> y) of type inout(const(int*)) to inout(int*) */
> }
> ----
>
> That code can't compile because g's inout return type says that it has
> to return a mutable result for a mutable argument x. But y is immutable,
> so that can't work.
>
> We see in the error message that `f(x, y)` results in a `inout(const
> int*)`. We can change g's return type to that (or `auto`) and the code
> compiles. `inout const` enforces that the result is const or immutable.
> It cannot be mutable.
>
> This raises a question: There is no analogous inout variant that goes
> the other way (to mutable and const but not immutable), is there?

No, the fact that immutable implicitly casts to const(inout) is a 
special property enabled by the knowledge that immutable data can NEVER 
change, so it's OK to assume it's (at least) const for all references. 
The same cannot be true of const or mutable.

>
> This code doesn't work, and I see no way to make it work:
>
> ----
> inout(int*) f(inout int* x, inout int* y)
> {
>     return y;
> }
>
> auto g(inout int* x)
> {
>     int* y;
>     return f(x, y);
> }
>
> void main()
> {
>     int* x;
>     int* r1 = g(x);
> }
> ----

This cannot work, because g() has no idea what the true mutability of x 
is. inout is not a template. This is why you can't implicitly cast inout 
to anything except const, and you can't implicitly cast anything to inout.

So it MUST return const(int *) (if you did auto r1 = g(x), typeof(r1) 
would be const(int *)).

-Steve


More information about the Digitalmars-d-learn mailing list