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

Reply via email to