inout and templates don't mix...

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Mar 24 07:59:35 PDT 2016


On 3/23/16 6:25 PM, Ali Çehreli wrote:
> On 03/23/2016 02:31 PM, cy wrote:
>
>  > struct Someop(Type) {
>  >    Type thing;
>  >    void foo() {
>  >      thing.bar();
>  >    }
>  > }
>  >
>  > struct Foo {
>  >    void bar() {
>  >      import std.stdio: writeln;
>  >      writeln("bar");
>  >    }
>  > }
>  >
>  > struct Bar {
>  >    void thingy(inout(Foo) foo) inout {
>  >      auto op = Someop(foo);
>
> The following is a workaround for this example:
>
>        auto op = Someop!Foo(foo);

I would be surprised if the original code worked regardless of inout 
status. Struct implicit ctors are not IFTI-compatible.

Note what is happening here in your update is likely not what the OP 
expects. Since Foo contains no indirections, it is a value type. So it 
can be implicitly cast from inout to mutable (same thing with Someop). 
As soon as you involve a pointer here, it would stop compiling.

>
> I'm not sure whether Someop's implicit constructor should take part in
> deducing Someop's Type template parameter.

There is no deduction.

However, you can specify that you are explicitly constructing an inout 
Someop:

auto op = inout(Someop!Foo)(foo);

However, this will not allow Bar to compile, since it calls op.foo, and 
Someop.foo is not inout, neither is Foo.bar, so neither can be called.

In this case, you need to mark Foo.bar and Someop.foo as inout. Marking 
Foo.bar as inout is probably acceptable, but marking Someop.foo as inout 
is tricky, since it's a wrapper, and can't predict what Type is going to 
allow.

This is one of the viral situations that frankly affects all the 
mutability modifiers.

-Steve


More information about the Digitalmars-d-learn mailing list