How to get an inout constructor working with a template wrapper
Steven Schveighoffer
schveiguy at gmail.com
Fri Jul 27 14:34:54 UTC 2018
On 7/23/18 8:02 AM, aliak wrote:
> On Sunday, 22 July 2018 at 23:11:09 UTC, Ali Çehreli wrote:
>> Without much confidence on my side, first, I think you need to make
>> the constructor parameter inout(T) as well. Otherwise, you may be
>> making a const(W!T) initialized with a non-const T.
>>
>> After that, I like the "type constructor" syntax in main_alt() below
>> (which works) but a better approach is to use a convenience function
>> like wrap() below:
>>
>> struct W(T) {
>> T val;
>> this(inout(T) val) inout {
>> this.val = val;
>> }
>> }
>>
>> class C {}
>>
>> void main_alt() {
>> auto a = W!C(new C);
>> auto b = immutable W!(immutable C)(new C);
>> }
>>
>> auto wrap(T)(inout T t) {
>> return inout(W!T)(t);
>> }
>>
>> void main() {
>> auto a = wrap(new C);
>> auto b = wrap(new immutable(C));
>> }
>>
>> Ali
>> "taklitlerinden sakınınız" :o)
>
> Thank you Ali! That helped :) I've gotten most of it sorted out now, and
> the factory wrap is definitely the way to go, it also turned out that
> inout(T) and inout T (so inout without parens) was surprisingly
> different (maybe it's a bug? - to test you can remove the parens around
> U on line 3 in this sample: https://run.dlang.io/is/gd5oxW
This seems like a bug to me.
The semantic difference is that inout(U) means the TYPE inout(U),
whereas inout U means the variable U has the STORAGE CLASS inout, which
also happens to make it an inout(U) type. As far as I know, the storage
class inout shouldn't have any other effect on the semantic meaning.
I can't imagine any difference there, but it appears to not recognize
that return should be inferred? I don't know.
> Also over there, line 24:
>
> auto si = wrap!(immutable int)(3);
>
> seems to be giving problems. Any ideas there? Error is:
>
> onlineapp.d(8): Error: inout on return means inout must be on a
> parameter as well for pure nothrow @nogc @safe
> inout(W!(immutable(int)))(immutable(int) t)
> onlineapp.d(23): Error: template instance
> `onlineapp.wrap!(immutable(int))` error instantiating
The problem here is that inout(immutable(int)) is equivalent to
immutable(int).
That is, all flavors of mutability are equivalent to immutable(int):
/*mutable*/(immutable(int)) => immutable(int)
const(immutable(int)) => immutable(int)
immutable(immutable(int)) => immutable(int)
So the compiler really looks at your wrap instantiation like this;
inout(W!(immutable(int))) wrap(immutable(int) t)
which triggers the (really bad) message.
I'd ask, why are you even worrying about explicit instantiation? Why not
just wrap(3)?
or (if you really want to test it) wrap(immutable(int)(3))?
>
> To make it compile successfully you can either:
>
> 1) Chance immutable to const, then it works for some reason.
Because immutable(const(int)) => immutable(int), so the compiler can't
remove the inout behind your back.
> 2) Change the line to: "auto si = wrap(cast(immutable int)3);" - i.e. do
> not explicitly provide type information.
Yep, do this :)
Note that the point of inout is 2-fold:
1. reduce template instantiations. In fact, wrap!int works for const,
mutable and immutable int.
2. ENSURE that the data isn't modified, even in the case of mutable
parameters.
-Steve
More information about the Digitalmars-d-learn
mailing list