How to get an inout constructor working with a template wrapper

Steven Schveighoffer schveiguy at gmail.com
Tue Jul 31 21:54:54 UTC 2018


On 7/31/18 5:29 PM, aliak wrote:
> On Tuesday, 31 July 2018 at 12:37:34 UTC, Steven Schveighoffer wrote:
>> On 7/29/18 1:46 PM, aliak wrote:
>>> On Sunday, 29 July 2018 at 12:45:48 UTC, Steven Schveighoffer wrote:
>>>>>
>>>>> Am I applying inout incorrectly?
>>>>
>>>> No, you need to apply it to wrap as well. I can't get run.dlang.io 
>>>> to work for posting a link, so here is my modified version:
>>>>
>>>
>>> Ah bugger, right!
>>>
>>> Ok so there's no way to make explicit instantiation involving 
>>> immutable work in the face of an inout parameter? Seems rather 
>>> inconsistent no?
>>
>> It's not that there's no way, the issue is simply that you are 
>> explicitly instantiating incorrectly.
>>
>> wrap!int(immutable(int)(3));
>>
> 
> Ok bear with me, but I'm really confused why 
> "wrap!int(immutable(int)(3))" is "correct".

Because inout is trying to combine all mutability modifiers into one. 
You want to specify the type, not the mutability, in the template 
parameter T.

Essentially, if this were a normal function that takes only ints, you 
would write it once for all mutabilities:

auto wrap(inout(int) x)

Which works for mutable, const, or immutable int.

> 
> This all seems very inconsistent:
> 
> 1. wrap!(int)(3); // ok
> 2. wrap!(const int)(3); // ok
> 3. wrap!(immutable int)(3); // nope
> 4. wrap!(int)(3); // ok
> 5. wrap!(const int)(const(int)(3)); // ok
> 6. wrap!(immutable int)(immutable(int)(3)); // ok!

This doesn't make sense. Can you post runnable code?

When I go back to your original failing example, and replace the 3 with 
immutable(int)(3), it still fails.

> 
> So for 3, compiler sees the instantiation:
> 
>   inout(W!(immutable int)) wrap(immutable(int))
> 
> If I understood you correctly?

Yes. You can see for yourself with pragma msg:

pragma(msg, typeof(t)); // immutable(int)

> 
> But then what does it see in number 6, which works fine?

I'm skeptical this is the case.

Note that you may only see the instantiation error ONCE.

> And why is 2 ok 
> if 3 is not?

because inout(const(T)) cannot have its inout removed.

> And finally, why can't the compiler leave the inout there 
> and then it doesn't need to complain about it?
It has to strip inout to be consistent -- we want canonical types. It's 
the same reason immutable(const(int)) is just immutable(int), and 
const(const(const(int))) is just const(int). Having the original types 
be left in place would make for some weird rules.

But the complaint is really the issue. Clearly inout is specified, so it 
shouldn't complain that it isn't.

-Steve


More information about the Digitalmars-d-learn mailing list