digitalmars.D.learn - Error: 'this' is only defined in non-static member functions,
- Matej Nanut (36/36) Jan 16 2012 Hey everyone,
- Timon Gehr (3/37) Jan 16 2012 Yes; It is extremely hard to solve the problem when there is no code
- Matej Nanut (12/59) Jan 17 2012 I will try to remove all snippets in my code that aren't relevant but st...
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (5/63) Jan 17 2012 DustMite is good for making test cases:
- H. S. Teoh (8/12) Jan 17 2012 [...]
- Matej Nanut (72/78) Jan 17 2012 That was my guess too =E2=80=94 but I'm not referencing the outer class....
- Timon Gehr (17/90) Jan 17 2012 I'm quite sure that the error in your code occurs for the same reason as...
- Matej Nanut (18/34) Jan 17 2012 re
- Timon Gehr (32/65) Jan 17 2012 I don't know if there is any, but I can explain to you the difference
- H. S. Teoh (51/62) Jan 17 2012 [...]
- H. S. Teoh (9/14) Jan 17 2012 [...]
- Matej Nanut (10/16) Jan 17 2012 I've been thinking on getting that for a while now. How up to date is it...
- Timon Gehr (9/29) Jan 17 2012 I think it is mostly in a good state. There are a few errata and some
- H. S. Teoh (18/32) Jan 17 2012 Well, D2 is a fast-evolving language, so any book can't possibly be 100%
- Jonathan M Davis (16/21) Jan 17 2012 If anything, it's _too_ up-to-date. There are a few relatively minor cha...
- Stewart Gordon (9/9) Jan 17 2012 For future reference and to elaborate on what others have said, if you'r...
Hey everyone, I, once again, have a problem with an error I can't seem to figure out! The situation: - a class, inherited by five other classes; - the class having a static function which returns one if its subclasses depending on the input of a string. Something like this: class Node { static Node parse(ref string s) { /* Get value to switch by, an enum. */ auto switchable = /* ... */; final switch (switchable) { case Blah.one: return new OneNode(s); case Blah.two: return new TwoNode(s); /* ... */ } } } And I get the mentioned error. I don't understand it: is it saying I'm using `this' in a static member function called `parse'? Am I insane; where am I referencing it? The other classes are in this form: class OneNode : Node { /* ... stuff ... */ this(ref string s) { /* Does stuff with `s'. */ } } Do you need more information? Thank you, Matej
Jan 16 2012
On 01/17/2012 12:49 AM, Matej Nanut wrote:Hey everyone, I, once again, have a problem with an error I can't seem to figure out! The situation: - a class, inherited by five other classes; - the class having a static function which returns one if its subclasses depending on the input of a string. Something like this: class Node { static Node parse(ref string s) { /* Get value to switch by, an enum. */ auto switchable = /* ... */; final switch (switchable) { case Blah.one: return new OneNode(s); case Blah.two: return new TwoNode(s); /* ... */ } } } And I get the mentioned error. I don't understand it: is it saying I'm using `this' in a static member function called `parse'? Am I insane; where am I referencing it? The other classes are in this form: class OneNode : Node { /* ... stuff ... */ this(ref string s) { /* Does stuff with `s'. */ } } Do you need more information?Yes; It is extremely hard to solve the problem when there is no code snippet given which exhibits the problematic behavior in question.
Jan 16 2012
I will try to remove all snippets in my code that aren't relevant but still exhibit the issue, when I find the time. What I forgot to mention is that this error appeared when I did some so-called "refactoring"; I moved a nested class out of its parent, since I wanted it visible on the outside. I moved it back now and reference it by Parent.Child.<stuff>, which is just as good, and the error isn't there anymore, but I still don't understa= nd it. I must have missed some variable renaming or something. Or I was just plain sloppy. As mentioned I will post a complete snippet with the error sometime until friday. On 17 January 2012 02:33, Timon Gehr <timon.gehr gmx.ch> wrote:On 01/17/2012 12:49 AM, Matej Nanut wrote:petHey everyone, I, once again, have a problem with an error I can't seem to figure out! The situation: - a class, inherited by five other classes; - the class having a static function which returns one =C2=A0 if its subclasses depending on the input of a string. Something like this: class Node { =C2=A0 static Node parse(ref string s) =C2=A0 { =C2=A0 =C2=A0 /* Get value to switch by, an enum. */ =C2=A0 =C2=A0 auto switchable =3D /* ... */; =C2=A0 =C2=A0 final switch (switchable) =C2=A0 =C2=A0 { =C2=A0 =C2=A0 =C2=A0 case Blah.one: return new OneNode(s); =C2=A0 =C2=A0 =C2=A0 case Blah.two: return new TwoNode(s); =C2=A0 =C2=A0 /* ... */ =C2=A0 =C2=A0 } =C2=A0 } } And I get the mentioned error. I don't understand it: is it saying I'm using `this' in a static member function called `parse'? Am I insane; where am I referencing it? The other classes are in this form: class OneNode : Node { =C2=A0 /* ... stuff ... */ =C2=A0 this(ref string s) =C2=A0 { =C2=A0 =C2=A0 /* Does stuff with `s'. */ =C2=A0 } } Do you need more information?Yes; It is extremely hard to solve the problem when there is no code snip=given which exhibits the problematic behavior in question.
Jan 17 2012
On 17-01-2012 12:23, Matej Nanut wrote:I will try to remove all snippets in my code that aren't relevant but still exhibit the issue, when I find the time. What I forgot to mention is that this error appeared when I did some so-called "refactoring"; I moved a nested class out of its parent, since I wanted it visible on the outside. I moved it back now and reference it by Parent.Child.<stuff>, which is just as good, and the error isn't there anymore, but I still don't understand it. I must have missed some variable renaming or something. Or I was just plain sloppy. As mentioned I will post a complete snippet with the error sometime until friday. On 17 January 2012 02:33, Timon Gehr<timon.gehr gmx.ch> wrote:DustMite is good for making test cases: https://github.com/CyberShadow/DustMite -- - AlexOn 01/17/2012 12:49 AM, Matej Nanut wrote:Hey everyone, I, once again, have a problem with an error I can't seem to figure out! The situation: - a class, inherited by five other classes; - the class having a static function which returns one if its subclasses depending on the input of a string. Something like this: class Node { static Node parse(ref string s) { /* Get value to switch by, an enum. */ auto switchable = /* ... */; final switch (switchable) { case Blah.one: return new OneNode(s); case Blah.two: return new TwoNode(s); /* ... */ } } } And I get the mentioned error. I don't understand it: is it saying I'm using `this' in a static member function called `parse'? Am I insane; where am I referencing it? The other classes are in this form: class OneNode : Node { /* ... stuff ... */ this(ref string s) { /* Does stuff with `s'. */ } } Do you need more information?Yes; It is extremely hard to solve the problem when there is no code snippet given which exhibits the problematic behavior in question.
Jan 17 2012
On Tue, Jan 17, 2012 at 12:23:55PM +0100, Matej Nanut wrote:I will try to remove all snippets in my code that aren't relevant but still exhibit the issue, when I find the time. What I forgot to mention is that this error appeared when I did some so-called "refactoring"; I moved a nested class out of its parent, since I wanted it visible on the outside.[...] This may be the cause of your trouble. If the nested class references members in the outer class, then moving it outside will break it, since it won't have an outer scope anymore. T -- Only boring people get bored. -- JM
Jan 17 2012
On 17 January 2012 16:54, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:This may be the cause of your trouble. If the nested class references members in the outer class, then moving it outside will break it, since it won't have an outer scope anymore. T -- Only boring people get bored. -- JMThat was my guess too =E2=80=94 but I'm not referencing the outer class. Th= e outer class is just using instances of the inner one. Also, the line number of the error points to =E2=80=98new=E2=80=99 statements in the static metho= d. (The calls which instantiate subclasses of the inner class.) If I do "return null" it works as well, without complaining. So it's not a referencing issue I think= . As you all seem eager to help, I will copy the entire class, without subclasses, to here. I will be grateful for any comments regarding the current issue at hand or about the code in general. The =E2=80=98new=E2=80=99-ed Nodes are defined like =E2=80=98class CostNode= : Node { ... }=E2=80=99. Another note, the outer class is an inner class of another class as well, if that makes a difference. Also, the outer class isn't really a class, it'= s a struct, but renaming that to =E2=80=98class=E2=80=99 doesn't change anyth= ing either. ---- code begin ---- class Node { static Node parse(ref string line) { string mnemonic =3D munch(line, "A-Z"); line =3D line.stripLeft(); auto op =3D mnemonic in mnemonics; if (!op) throw new Exception("Unknown mnemonic: `" ~ mnemonic ~"= '"); final switch (*op) { case NodeType.COST: return new CostNode(line); case NodeType.PAUSE: return new PauseNode(line); case NodeType.COLDR: return new ColDrNode(line); case NodeType.COLRA: return new ColRaNode(line); case NodeType.DROP: return new DropNode(line); case NodeType.RAISE: return new RaiseNode(line); } /* Doing something like `return new Node()' doesn't work ei= ther. * Only `return null' works here. */ } enum NodeType : ubyte { COST, PAUSE, COLDR, COLRA, DROP, RAISE } static immutable NodeType[string] mnemonics; static this() { mnemonics =3D [ "COST" : NodeType.COST, "PAUSE" : NodeType.PAUSE, "COLDR" : NodeType.COLDR, "COLRA" : NodeType.COLRA, "DROP" : NodeType.DROP, "RAISE" : NodeType.RAISE ]; } } ---- code end ----
Jan 17 2012
On 01/17/2012 06:02 PM, Matej Nanut wrote:On 17 January 2012 16:54, H. S. Teoh<hsteoh quickfur.ath.cx> wrote:I'm quite sure that the error in your code occurs for the same reason as in the following code snippet: class C{ class D{} static make(){return new D();} // error } You can fix it by making D static: class C{ static class D{} static make(){return new D();} // ok } The reason is that non-static inner classes have an implicit 'outer' property that links to the class it was created with. Therefore, to construct them inside a member function, the implicit 'this' pointer is needed. If the 'outer' property is actually unwanted, it is best to declare inner classes as static.This may be the cause of your trouble. If the nested class references members in the outer class, then moving it outside will break it, since it won't have an outer scope anymore. T -- Only boring people get bored. -- JMThat was my guess too — but I'm not referencing the outer class. The outer class is just using instances of the inner one. Also, the line number of the error points to ‘new’ statements in the static method. (The calls which instantiate subclasses of the inner class.) If I do "return null" it works as well, without complaining. So it's not a referencing issue I think. As you all seem eager to help, I will copy the entire class, without subclasses, to here. I will be grateful for any comments regarding the current issue at hand or about the code in general. The ‘new’-ed Nodes are defined like ‘class CostNode : Node { ... }’. Another note, the outer class is an inner class of another class as well, if that makes a difference. Also, the outer class isn't really a class, it's a struct, but renaming that to ‘class’ doesn't change anything either. ---- code begin ---- class Node { static Node parse(ref string line) { string mnemonic = munch(line, "A-Z"); line = line.stripLeft(); auto op = mnemonic in mnemonics; if (!op) throw new Exception("Unknown mnemonic: `" ~ mnemonic ~"'"); final switch (*op) { case NodeType.COST: return new CostNode(line); case NodeType.PAUSE: return new PauseNode(line); case NodeType.COLDR: return new ColDrNode(line); case NodeType.COLRA: return new ColRaNode(line); case NodeType.DROP: return new DropNode(line); case NodeType.RAISE: return new RaiseNode(line); } /* Doing something like `return new Node()' doesn't work either. * Only `return null' works here. */ } enum NodeType : ubyte { COST, PAUSE, COLDR, COLRA, DROP, RAISE } static immutable NodeType[string] mnemonics; static this() { mnemonics = [ "COST" : NodeType.COST, "PAUSE" : NodeType.PAUSE, "COLDR" : NodeType.COLDR, "COLRA" : NodeType.COLRA, "DROP" : NodeType.DROP, "RAISE" : NodeType.RAISE ]; } } ---- code end ----
Jan 17 2012
On 17 January 2012 18:29, Timon Gehr <timon.gehr gmx.ch> wrote:I'm quite sure that the error in your code occurs for the same reason as =inthe following code snippet: class C{ =C2=A0 =C2=A0class D{} =C2=A0 =C2=A0static make(){return new D();} // error } You can fix it by making D static: class C{ =C2=A0 =C2=A0static class D{} =C2=A0 =C2=A0static make(){return new D();} // ok } The reason is that non-static inner classes have an implicit 'outer' property that links to the class it was created with. Therefore, to construct them inside a member function, the implicit 'this' pointer is needed. If the 'outer' property is actually unwanted, it is best to decla=reinner classes as static.Yes! If I move the class and its subclasses out of its outer class, and dec= lare them all static, it works! Note that your `make' function is being called within class `D' in my examp= le, if I replace the names. However, the same thing applies. Your explanation was nice, but now I'd like to know what the difference of = a non-static vs. a static class is, if they're defined top-level? Or are they= then the same? I don't expect anyone to thoroughly explain things to me, but pointing out a good source, like a link or a book, would be really helpful. I lack general knowledge in the OOP area and must really learn more about it, as I've always been programming in C and could easily get away with it as we were doing small-ish programs at university.
Jan 17 2012
On 01/17/2012 06:58 PM, Matej Nanut wrote:On 17 January 2012 18:29, Timon Gehr<timon.gehr gmx.ch> wrote:Indeed they are the same. Anything top-level is implicitly static in D.I'm quite sure that the error in your code occurs for the same reason as in the following code snippet: class C{ class D{} static make(){return new D();} // error } You can fix it by making D static: class C{ static class D{} static make(){return new D();} // ok } The reason is that non-static inner classes have an implicit 'outer' property that links to the class it was created with. Therefore, to construct them inside a member function, the implicit 'this' pointer is needed. If the 'outer' property is actually unwanted, it is best to declare inner classes as static.Yes! If I move the class and its subclasses out of its outer class, and declare them all static, it works! Note that your `make' function is being called within class `D' in my example, if I replace the names. However, the same thing applies. Your explanation was nice, but now I'd like to know what the difference of a non-static vs. a static class is, if they're defined top-level? Or are they then the same?I don't expect anyone to thoroughly explain things to me, but pointing out a good source, like a link or a book, would be really helpful.I don't know if there is any, but I can explain to you the difference between static and non-static nested classes in detail: class A{ int x; static class B{void echo(){writeln(x);}} // n.g. } class A{ int x; class B{void echo(){writeln(x);}} // ok } In other words, non-static nested classes can reference non-static fields of the enclosing class. In order to provide that functionality, non-static nested classes need the implicit 'outer' field. The first snippet is effectively rewritten to something like the following: class A{ int x; class B{A __outer; void echo(){writeln(__outer.x);} } Therefore, for constructing a class instance of type A.B, an instance of A must be provided as an initializer for the 'outer' field. If an instance of B is created in a member of A, the 'this' pointer gets used (and hence is required to be present), but you can also do: void main() { auto a = new A; auto b = a.new B; // construct an 'A.B' with 'a' in implicit 'outer' field a.x = 100; b.echo(); // writes '100' } This is probably one of the more obscure features of D. =)I lack general knowledge in the OOP area and must really learn more about it, as I've always been programming in C and could easily get away with it as we were doing small-ish programs at university.
Jan 17 2012
On Tue, Jan 17, 2012 at 08:25:28PM +0100, Timon Gehr wrote: [...]In other words, non-static nested classes can reference non-static fields of the enclosing class. [...][...]void main() { auto a = new A; auto b = a.new B; // construct an 'A.B' with 'a' in implicit 'outer' field a.x = 100; b.echo(); // writes '100' } This is probably one of the more obscure features of D. =)[...] It totally makes sense though. In some of my past C++ projects, I've had to use the inner class idiom quite often. Of course, it's not directly supported by the language so I ended up writing lots of little nested classes like this: class outer { ... class inner1 { outer *ctxt; ... inner1(outer *c) : ctxt(c) {} }; ... class inner2 { outer *ctxt; ... inner2(outer *c) : ctxt(c) {} }; ... void f() { ... inner1 *helper1 = new inner1(this); register_callback(helper1, ...); ... inner2 *helper2 = new inner2(this); register_callback(helper2, ...); ... } }; After a while, it just got really really tedious to keep writing the same boilerplate code over and over again. In D, a lot of that redundancy can be gotten rid of (no need for explicit outer pointers in the inner classes, eliminate ctor parameters), just because (non-static) inner classes automatically get an outer pointer, and you can just instantiate them with: auto helper1 = this.new inner1; But D lets you do even better. Instead of creating an inner class, you can just pass a delegate to do what needs to be done: void f() { ... register_callback((args) { this.state1++; }, ...); register_callback((args) { this.state2++; }, ...); ... } Much more readable, and much less room for bugs to hide in. T -- "Maybe" is a strange word. When mom or dad says it it means "yes", but when my big brothers say it it means "no"! -- PJ jr.
Jan 17 2012
On Tue, Jan 17, 2012 at 06:58:55PM +0100, Matej Nanut wrote: [...]Your explanation was nice, but now I'd like to know what the difference of a non-static vs. a static class is, if they're defined top-level? Or are they then the same? I don't expect anyone to thoroughly explain things to me, but pointing out a good source, like a link or a book, would be really helpful.[...] Andrei's book ("The D Programming Language") is quite thorough in explaining these D constructs. It's a highly recommended buy if you're doing serious work in D. T -- The two rules of success: 1. Don't tell everything you know. -- YHL
Jan 17 2012
On 17 January 2012 19:07, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:Andrei's book ("The D Programming Language") is quite thorough in explaining these D constructs. It's a highly recommended buy if you're doing serious work in D. T -- The two rules of success: 1. Don't tell everything you know. -- YHLI've been thinking on getting that for a while now. How up to date is it? Or does it explain such general concepts that I shouldn't be worried about that at all? Everyone seems to be recommending it so I don't see why I shouldn't get it. A free university period is also coming up, so that might be a great way to spend my available time. I'm definitely serious about learning and using D. I've been impressed with it since I first saw it and I intend to do as much work with it as possible. I'm not _doing_ any serious work with it yet, though. In fact, none of the work I do could be considered very serious at all. :)
Jan 17 2012
On 01/17/2012 07:13 PM, Matej Nanut wrote:On 17 January 2012 19:07, H. S. Teoh<hsteoh quickfur.ath.cx> wrote:I think it is mostly in a good state. There are a few errata and some unmentioned features because D is/was somewhat of a moving/improving target. On the other hand, many recent bug fixes were targeted at making the implementation consistent with the specification in TDPL.Andrei's book ("The D Programming Language") is quite thorough in explaining these D constructs. It's a highly recommended buy if you're doing serious work in D. T -- The two rules of success: 1. Don't tell everything you know. -- YHLI've been thinking on getting that for a while now. How up to date is it?Or does it explain such general concepts that I shouldn't be worried about that at all?I don't think you need to be worried, just be prepared that a few code samples may not compile without minimal fixes.Everyone seems to be recommending it so I don't see why I shouldn't get it. A free university period is also coming up, so that might be a great way to spend my available time.Indeed. When I read it, I have found my time well spent. It is very well written.I'm definitely serious about learning and using D. I've been impressed with it since I first saw it and I intend to do as much work with it as possible. I'm not _doing_ any serious work with it yet, though. In fact, none of the work I do could be considered very serious at all. :)
Jan 17 2012
On Tue, Jan 17, 2012 at 07:13:02PM +0100, Matej Nanut wrote:On 17 January 2012 19:07, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:[...]Andrei's book ("The D Programming Language") is quite thorough in explaining these D constructs. It's a highly recommended buy if you're doing serious work in D.I've been thinking on getting that for a while now. How up to date is it? Or does it explain such general concepts that I shouldn't be worried about that at all? Everyone seems to be recommending it so I don't see why I shouldn't get it. A free university period is also coming up, so that might be a great way to spend my available time.Well, D2 is a fast-evolving language, so any book can't possibly be 100% up to date. :) But having said that, what's covered in the book is pretty close to the current state of D2. The basics haven't changed, so you don't really have to worry about that. When you get to the level where it starts to matter, you probably don't need the book anymore (or only need it for reference) anyway. :)I'm definitely serious about learning and using D. I've been impressed with it since I first saw it and I intend to do as much work with it as possible.I've also been impressed with D since I first stumbled across it late last year. I've been using C/C++ for almost 2 decades, but after tasting D's power in a recent small project, I have to confess that I just can't go back to C/C++ for my personal projects anymore. The more I use D the more I like it.I'm not _doing_ any serious work with it yet, though. In fact, none of the work I do could be considered very serious at all. :)Isn't that how we all start out, though? Tinker with the language in toy projects that eventually become the basis for something more serious. T -- 2+2=4. 2*2=4. 2^2=4. Therefore, +, *, and ^ are the same operation.
Jan 17 2012
On Tuesday, January 17, 2012 19:13:02 Matej Nanut wrote:I've been thinking on getting that for a while now. How up to date is it? Or does it explain such general concepts that I shouldn't be worried about that at all? Everyone seems to be recommending it so I don't see why I shouldn't get it. A free university period is also coming up, so that might be a great way to spend my available time.If anything, it's _too_ up-to-date. There are a few relatively minor changes which have been made to the language since its release (e.g. weak vs strong purity and attribute inference for templated functions), but for the most part if TDPL doesn't match what dmd is doing, it's because features aren't fully implemented yet which should be (e.g. alias this works, but according to TDPL, you should be able to have multiple alias this-es per type - which you can't currently do). There has been a recent push though to fix the remaining issues where the compiler doesn't yet match TDPL. I actually think that TDPL is the best programming language book that I've ever read. It's very well written and _way_ more informative than the rather sparse online documentation. I'd been programming in D for a while when I read it, and there were all kinds of stuff in there that I didn't know about. I really think that it's a must have for any serious D programmer. - Jonathan M Davis P.S. TDPL's errata is here: http://erdani.com/tdpl/errata/
Jan 17 2012
For future reference and to elaborate on what others have said, if you're asking for help solving a problem with your code, then please: 1. Post a small, self-contained testcase that demonstrates the problem straight out of the box. Tips here: http://www.sscce.org/ 2. Post full compiler output (or runtime output, if it's a runtime problem) from the testcase. 3. State what compiler version and operating system you are using, as it may be relevant. Stewart.
Jan 17 2012