digitalmars.D.learn - opDispatch
- Danny (21/21) Dec 25 2014 Hi,
- Tobias Pankrath (18/40) Dec 25 2014 I am not sure why your code even compiles, but this works better:
- Danny (10/10) Dec 25 2014 I tried to make it even simpler to get to the core of the problem
- Danny (1/1) Dec 25 2014 Tobias: Thanks! Your version works. But now it's read-only.
- Adam D. Ruppe (7/8) Dec 25 2014 Make the opDispatch function return ref and then you can write to
- Danny (8/8) Dec 25 2014 Adam: Thanks, that was very illuminating! I tried and these work
- Tobias Pankrath (6/14) Dec 25 2014 http://dlang.org/traits
- Danny (4/6) Dec 25 2014 Hmm, I'm not really worried about safety in this case (in many
- Tobias Pankrath (3/9) Dec 25 2014 Not sure how that could happen. I thought utf-8 was closed under
- Adam D. Ruppe (6/8) Dec 25 2014 There's no this at compile time though which is why it complains.
- Adam D. Ruppe (36/45) Dec 25 2014 That won't work anyway since X doesn't implement opDispatch - it
Hi, I'm trying to learn how opDispatch works. Unfortunately, a very simple example already doesn't work (error: no property 'a' for type 'Foo'): import std.stdio : writeln; struct X { int a; } class Foo { X value; template opDispatch(string s) { value.opDispatch!(s) opDispatch; } } int main() { auto f = new Foo; writeln(f.a); return 0; } What am I missing? Is there another way to make Foo forward all unknown things to X ?
Dec 25 2014
On Thursday, 25 December 2014 at 15:50:07 UTC, Danny wrote:Hi, I'm trying to learn how opDispatch works. Unfortunately, a very simple example already doesn't work (error: no property 'a' for type 'Foo'): import std.stdio : writeln; struct X { int a; } class Foo { X value; template opDispatch(string s) { value.opDispatch!(s) opDispatch; } } int main() { auto f = new Foo; writeln(f.a); return 0; } What am I missing? Is there another way to make Foo forward all unknown things to X ?I am not sure why your code even compiles, but this works better: import std.stdio; struct X { int a; } class XX { X value; auto opDispatch(string s)() { mixin("return value." ~ s ~ ";"); } } void main() { XX x = new XX(); writeln(x.a); }
Dec 25 2014
I tried to make it even simpler to get to the core of the problem I'm having: ... template opDispatch(string s) { alias value.a opDispatch; } The compiler then complains: error: need 'this' for 'a' of type 'int' I can only think: And? It's right there... it's a class instance, it has 'this'.
Dec 25 2014
Tobias: Thanks! Your version works. But now it's read-only.
Dec 25 2014
On Thursday, 25 December 2014 at 16:02:48 UTC, Danny wrote:Tobias: Thanks! Your version works. But now it's read-only.Make the opDispatch function return ref and then you can write to it. Alternatively, write a second setter opDispatch overload: T opDispatch(string name, T)(T rhs) { return mixin("value." ~ name ~ " = rhs"); }
Dec 25 2014
Adam: Thanks, that was very illuminating! I tried and these work indeed. Is there a function like opDispatch which can be used (at compile time) to refer to something by name whether or not it's custom? (to access something like "value.a" safely. mixin and string concatenation looks like would have problems with special characters easily) (Something like getattr(x, "a") in Python)
Dec 25 2014
On Thursday, 25 December 2014 at 16:24:10 UTC, Danny wrote:Adam: Thanks, that was very illuminating! I tried and these work indeed. Is there a function like opDispatch which can be used (at compile time) to refer to something by name wh ether or not it's custom? (to access something like "value.a" safely. mixin and string concatenation looks like would have problems with special characters easily) (Something like getattr(x, "a") in Python)http://dlang.org/traits __traits(getMember, x, "a"). Not sure how that works together with opDispatch. I am not sure why you see safety reasons at compile time though. If there is no such attribute, you'll just get an error.
Dec 25 2014
Not sure how that works together with opDispatch. I am not sure why you see safety reasons at compile time though.Hmm, I'm not really worried about safety in this case (in many other slightly different scenarios I am). More worried about strange Unicode characters in fields I have no control over (in other libraries etc) messing it up for no reason.
Dec 25 2014
On Thursday, 25 December 2014 at 16:41:51 UTC, Danny wrote:Not sure how that could happen. I thought utf-8 was closed under concatenation.Not sure how that works together with opDispatch. I am not sure why you see safety reasons at compile time though.Hmm, I'm not really worried about safety in this case (in many other slightly different scenarios I am). More worried about strange Unicode characters in fields I have no control over (in other libraries etc) messing it up for no reason.
Dec 25 2014
On Thursday, 25 December 2014 at 15:59:44 UTC, Danny wrote:I can only think: And? It's right there... it's a class instance, it has 'this'.There's no this at compile time though which is why it complains. What you're trying to do is an expression alias which D doesn't support (and sometimes it gives the error message "alias expressions are not allowed", not sure why it didn't here..). If you made your opDispatch a function it would work though.
Dec 25 2014
On Thursday, 25 December 2014 at 15:50:07 UTC, Danny wrote:struct X { int a; } class Foo { X value; template opDispatch(string s) { value.opDispatch!(s) opDispatch;That won't work anyway since X doesn't implement opDispatch - it needs to be written in the function by the user to be used. opDispatch is a function called when a member isn't found. So with yours: Foo.value -> value is found, so opDispatch is never called. Foo.a -> value not found, the compiler tries Foo.opDispatch!"a". If that compiles, it works. Otherwise, it issues the "has no property" error. A few tips with opDispatch: * since you just get "no such property" if it fails, you don't know *why* it failed. To get a better error message when you know it should be working but isn't, try writing it out yourself: foo.opDispatch!"a"; and the compiler will give you more information about why it didn't work. * opDispatch is often a function. It doesn't have to be, but it usually is: auto opDispatch(string name)() { return something; }Is there another way to make Foo forward all unknown things to X ?You could try writing: auto opDispatch(string name)() { return mixin("value." ~ name); } That would do it. There is also alias this and opDot that does forwarding. I can't find the docs for them right now but add "alias value this;" to your class for one option or.... I think "X* opDot() { return &value; }" for the other. alias this forwards any unknown properties to another member and also allows implicit conversion. It is kinda like how inheritance from a base class works. opDot is an older function that might be removed at some point, it predates opDispatch and alias this, but what it does is forward to a return value when it isn't found.
Dec 25 2014