Jump to page: 1 2
Thread overview
Error: 'this' is only defined in non-static member functions, not parse
Jan 16, 2012
Matej Nanut
Jan 17, 2012
Timon Gehr
Jan 17, 2012
Matej Nanut
Jan 17, 2012
H. S. Teoh
Jan 17, 2012
Matej Nanut
Jan 17, 2012
Timon Gehr
Jan 17, 2012
Matej Nanut
Jan 17, 2012
Timon Gehr
Jan 17, 2012
H. S. Teoh
Jan 17, 2012
H. S. Teoh
Jan 17, 2012
Matej Nanut
Jan 17, 2012
Timon Gehr
Jan 17, 2012
H. S. Teoh
Jan 17, 2012
Jonathan M Davis
Jan 18, 2012
Stewart Gordon
January 16, 2012
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
January 17, 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.

January 17, 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 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:
> 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.
>
January 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:
>> 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.
>>

DustMite is good for making test cases: https://github.com/CyberShadow/DustMite

-- 
- Alex
January 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
January 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. -- JM

That 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 ----
January 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:
>> 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
>
> That 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 ----

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.
January 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 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 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.
January 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
January 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. -- YHL

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.

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. :)
« First   ‹ Prev
1 2