www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - class is forward referenced when looking for 'v'

reply "Amber Thralll" <amber.rose.thrall gmail.com> writes:
I ran into an issue with cross referencing to classes, that I 
can't figure out.  I reproduced the issue below:

import std.stdio;

class Base(t)
{
	public void Foo(A!(t) a)
	{
		writeln("Base.Foo(A a)");
	}

	public void Foo(B!(t) a)
	{
		writeln("Base.Foo(B a)");
	}
};

class A(t) : Base!(t)
{
	public t v;
	this(t v)
	{
		this.v = v;
	}
}

class B(t) : Base!(t)
{
	public override void Foo(A!(t) a)
	{
		writeln("A: ", a.v);
	}
}

int main()
{
	A!int a = new A!(int)(1);
	B!int b = new B!(int)();

	a.Foo(b);
	b.Foo(a);

	return 0;
}

And the errors dmd returns:
test.d(16): Error: class test.A!int.A is forward referenced when 
looking for 'v'
test.d(16): Error: class test.A!int.A is forward referenced when 
looking for 'opDot'
test.d(16): Error: class test.A!int.A is forward referenced when 
looking for 'opDispatch'
test.d(29): Error: no property 'v' for type 'test.A!int.A'
test.d(10): Error: template instance test.B!int error 
instantiating
test.d(16):        instantiated from here: Base!int
test.d(35):        instantiated from here: A!int

Is this a bug in D?  Or am I doing something wrong?
Jan 29 2015
next sibling parent "David Monagle" <david.monagle intrica.com.au> writes:
It's a bit hard to know where to start here. It's not obvious 
from your code what you are trying to achieve.

In essence, you do have a circular reference as Base has 
functions that use a types A and B which are derived from the 
Base. I don't see how the complier could be asked to resolve this.

You are using a curious mix of tempting and inheritance, but 
depending one what you are trying to achieve, you may only need 
one or the other.

If you want classes other than A to recognise the value "v", then 
you should define a "v" property either in the Base class, a 
class derived from it or in an interface. This will allow you to 
use the correct overloading (or "static if" in templating) to 
catch the scenario of it being passed into the Foo function.

As I say. This is not a great real world example so it's hard to 
answer without a better explanation of what you are trying to do. 
It is not, however a bug in the compiler.

Just another note. "public" is redundant for a class.
Jan 29 2015
prev sibling parent reply "Kenji Hara" <k.hara.pg gmail.com> writes:
On Friday, 30 January 2015 at 00:09:17 UTC, Amber Thralll wrote:
 And the errors dmd returns:
 test.d(16): Error: class test.A!int.A is forward referenced 
 when looking for 'v'
 test.d(16): Error: class test.A!int.A is forward referenced 
 when looking for 'opDot'
 test.d(16): Error: class test.A!int.A is forward referenced 
 when looking for 'opDispatch'
 test.d(29): Error: no property 'v' for type 'test.A!int.A'
 test.d(10): Error: template instance test.B!int error 
 instantiating
 test.d(16):        instantiated from here: Base!int
 test.d(35):        instantiated from here: A!int

 Is this a bug in D?  Or am I doing something wrong?
In D, forward reference resolution should have consistent result for template classes and non-template ones. If the code is rewritten to non-template version: import std.stdio; class Base { public void Foo(A a) { writeln("Base.Foo(A a)"); } public void Foo(B a) { writeln("Base.Foo(B a)"); } }; class A : Base { public int v; this(int v) { this.v = v; } } class B : Base { public override void Foo(A a) { writeln("A: ", a.v); } } int main() { A a = new A(1); B b = new B(); a.Foo(b); b.Foo(a); return 0; } Compiler properly resolves forward references. Therefore, it's definitely a compiler bug, and the template version should be accepted. I filed the issue in bugzilla: https://issues.dlang.org/show_bug.cgi?id=14083 And will open a new pull request to fix compiler. Kenji Hara
Jan 30 2015
parent "Amber Thralll" <amber.rose.thrall gmail.com> writes:
 class Base
 {
     public void Foo(A a)
     {
         writeln("Base.Foo(A a)");
     }

     public void Foo(B a)
     {
         writeln("Base.Foo(B a)");
     }
 };

 Compiler properly resolves forward references. Therefore, it's 
 definitely a compiler bug, and the template version should be 
 accepted.

 I filed the issue in bugzilla:
 https://issues.dlang.org/show_bug.cgi?id=14083

 And will open a new pull request to fix compiler.

 Kenji Hara
In the mean time I've found removing the overridden methods from the Base class, works with templates.
Jan 30 2015