digitalmars.D.learn - Capturing by reference with "visit" from std.variant
- Smaehtin (21/21) Feb 20 2018 I'm trying to understand why the following doesn't work:
I'm trying to understand why the following doesn't work: import std.stdio; import std.variant; void main() { Algebraic!(string, int) test = "Test"; test.tryVisit!( (ref string s) { s = "Why does this not work?"; } ); writeln(test); } But this works fine: *test.peek!string = "Works fine"; As far as I can tell, the "visit" template expands to something that ends up calling my handler like this: if (auto ptr = variant.peek!T) { handler(*ptr); } But seeing as the handler in my case takes a reference, shouldn't that work just fine? What am I missing?
Feb 20 2018
On Tuesday, 20 February 2018 at 16:01:11 UTC, Smaehtin wrote:I'm trying to understand why the following doesn't work: import std.stdio; import std.variant; void main() { Algebraic!(string, int) test = "Test"; test.tryVisit!( (ref string s) { s = "Why does this not work?"; } ); writeln(test); } But this works fine: *test.peek!string = "Works fine"; As far as I can tell, the "visit" template expands to something that ends up calling my handler like this: if (auto ptr = variant.peek!T) { handler(*ptr); } But seeing as the handler in my case takes a reference, shouldn't that work just fine? What am I missing?Your lambda is called, but you can't change the variant value trough that reference. Test with: import std.stdio; import std.variant; void main() { Algebraic!(string, int) test = "Test"; test.tryVisit!( (ref string s) { writeln("Why does this work? ", s); } ); writeln(test); } You should get: Why does this work? Test Test
Feb 20 2018
On Tuesday, 20 February 2018 at 16:15:56 UTC, Radu wrote:On Tuesday, 20 February 2018 at 16:01:11 UTC, Smaehtin wrote:Then my question is: Why can't I change the variant through the reference in the lambda? Seeing as this works just fine: void main() { Algebraic!(string, int) test = "Test"; changeIt(*test.peek!string); writeln(test); } void changeIt(ref string s) { s = "Changed"; } Prints: ChangedI'm trying to understand why the following doesn't work: import std.stdio; import std.variant; void main() { Algebraic!(string, int) test = "Test"; test.tryVisit!( (ref string s) { s = "Why does this not work?"; } ); writeln(test); } But this works fine: *test.peek!string = "Works fine"; As far as I can tell, the "visit" template expands to something that ends up calling my handler like this: if (auto ptr = variant.peek!T) { handler(*ptr); } But seeing as the handler in my case takes a reference, shouldn't that work just fine? What am I missing?Your lambda is called, but you can't change the variant value trough that reference. Test with: import std.stdio; import std.variant; void main() { Algebraic!(string, int) test = "Test"; test.tryVisit!( (ref string s) { writeln("Why does this work? ", s); } ); writeln(test); } You should get: Why does this work? Test Test
Feb 20 2018
On Tuesday, 20 February 2018 at 16:20:45 UTC, Smaehtin wrote:On Tuesday, 20 February 2018 at 16:15:56 UTC, Radu wrote:Okay, so I realized this happens because the variant parameter is getting passed down to the "visitImpl" function by value. Wouldn't it make sense to pass the arguments using "auto ref" in this case? This is the code I'm talking about: https://github.com/dlang/phobos/blob/9021bd36b97d247cba1def9ce12eca64efee61a5/std/variant.d#L2170 Changing it to "auto ref" would allow capturing by reference in the handlers, but I'm not really sure if it would have any negative side-effects.On Tuesday, 20 February 2018 at 16:01:11 UTC, Smaehtin wrote:Then my question is: Why can't I change the variant through the reference in the lambda? Seeing as this works just fine: void main() { Algebraic!(string, int) test = "Test"; changeIt(*test.peek!string); writeln(test); } void changeIt(ref string s) { s = "Changed"; } Prints: ChangedI'm trying to understand why the following doesn't work: import std.stdio; import std.variant; void main() { Algebraic!(string, int) test = "Test"; test.tryVisit!( (ref string s) { s = "Why does this not work?"; } ); writeln(test); } But this works fine: *test.peek!string = "Works fine"; As far as I can tell, the "visit" template expands to something that ends up calling my handler like this: if (auto ptr = variant.peek!T) { handler(*ptr); } But seeing as the handler in my case takes a reference, shouldn't that work just fine? What am I missing?Your lambda is called, but you can't change the variant value trough that reference. Test with: import std.stdio; import std.variant; void main() { Algebraic!(string, int) test = "Test"; test.tryVisit!( (ref string s) { writeln("Why does this work? ", s); } ); writeln(test); } You should get: Why does this work? Test Test
Feb 20 2018