digitalmars.D.learn - inout and templates don't mix...
- cy (51/51) Mar 23 2016 halp
- =?UTF-8?Q?Ali_=c3=87ehreli?= (6/21) Mar 23 2016 The following is a workaround for this example:
- Steven Schveighoffer (20/42) Mar 24 2016 I would be surprised if the original code worked regardless of inout
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... }
Mar 23 2016
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
Mar 23 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
Mar 24 2016