Re: inout and templates don't mix...

2016-03-24 Thread Steven Schveighoffer via Digitalmars-d-learn

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


Re: inout and templates don't mix...

2016-03-23 Thread Ali Çehreli via Digitalmars-d-learn

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'm not sure whether Someop's implicit constructor should take part in 
deducing Someop's Type template parameter.


Ali



inout and templates don't mix...

2016-03-23 Thread cy via Digitalmars-d-learn

halp

There's a module that tries to define complex operations on both 
const and non-const structs, since it's the same operation for 
both. So every function that invokes those operations is 
copy-pasted twice, just with "const" added. Switching to inout to 
eliminate that huge amount of code duplication causes an error, I 
can't figure out how to fix.


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);
op.foo();
  }
}

void main() {
  Foo foo;
  Bar bar;
  bar.thingy(foo);
}

=>

Error: struct derp.Someop cannot deduce function from argument 
types !()(inout(Foo))


if I put in Someop!(typeof(foo))(foo) it gives the error:

Error: variable derp.Someop!(inout(Foo)).Someop.thing only 
parameters or stack based variables can be inout


...even though Someop is a struct allocated on the stack.

What I'm dealing with is like:

struct Bar {
  void thingy(Foo foo) {
auto op = Someop(foo);
//...lotsastuff...
op.foo();
  }
  void thingy(const(Foo) foo) const {
auto op = Someop(foo);
//...lotsastuff...
op.foo();
  }
  // repeat ad-nauseum...
}