www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - template forward reference

reply C. Dunn <cdunn2001 gmail.com> writes:
This works:
<code>
class Foo(T){
  int bar(){
    return A.hi();
  }
};

class A{
  static int hi(){
    return 0;
  }

  F!(char) x;
};
</code>

But if I split these into 2 separate modules, where each module imports the
other, then the module with class A does not compile:
  Error: forward reference to 'Foo!(char)'
  Error: F is used as a type

If I make the template class a regular class, it compiles fine.  I understand
that cyclic template specializations could create problems, but I don't see why
moving a template into a separate module fails.  This works easily in C++ by
just forward-declaring class A.

Why does this not work?  Are there plans to support it in the future?
Jul 30 2007
next sibling parent reply Witold Baryluk <baryluk smp.if.uj.edu.pl> writes:
C. Dunn wrote:
 
 Why does this not work?  Are there plans to support it in the future?
Jul 31 2007
parent reply C. Dunn <cdunn2001 gmail.com> writes:
Witold Baryluk Wrote:

I do appreciate the response, but no, this is not the same bug. In my case, if Foo is not a template, everything compiles and links. It is somewhat related So it may be a related problem, but it is far more severe than just a restriction against "nested functions within a function and autotype declarations". I'm doing something very simple -- simple enough that it compiles for non-templates. It's really a problem with templates themselves. And it works fine if it's all in the same file. So it's a combination of 'import' and 'template'. ... I have found a work-around: If I compile the separate modules simultaneously, it works fine, even though it still produces separate .o files. Curious. dmd -c fooA.d fooFoo.d produces fooA.o and fooFoo.o but dmd -c fooFoo.d produces fooA.d(9): template instance forward reference to template declaration Foo(T) fooA.d(9): Error: Foo!(char) is used as a type It seems like an awkward solution, but at least it works.
Jul 31 2007
parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
C. Dunn wrote:
 Witold Baryluk Wrote:
 

I do appreciate the response, but no, this is not the same bug. In my case, if Foo is not a template, everything compiles and links. It is somewhat So it may be a related problem, but it is far more severe than just a restriction against "nested functions within a function and autotype declarations". I'm doing something very simple -- simple enough that it compiles for non-templates. It's really a problem with templates themselves. And it works fine if it's all in the same file. So it's a combination of 'import' and 'template'. ... I have found a work-around: If I compile the separate modules simultaneously, it works fine, even though it still produces separate .o files. Curious. dmd -c fooA.d fooFoo.d produces fooA.o and fooFoo.o but dmd -c fooFoo.d produces fooA.d(9): template instance forward reference to template declaration Foo(T) fooA.d(9): Error: Foo!(char) is used as a type It seems like an awkward solution, but at least it works.
Goodness. That looks familiar. I used to have all kinds of problems with that in Pyd, but some DMD version or other cleared it all up. Which version of the compiler are you using? -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org
Jul 31 2007
prev sibling next sibling parent reply C. Dunn <cdunn2001 gmail.com> writes:
I was really hoping to see a response to this.  It's going to prevent me from
using "D" at all.  Because of forward declarations, templates are more flexible
in C++.  This problem really needs to be addressed.  I'm willing to provide as
much info as necessary.

I kept the OP short, but I've actually tried a variety of ways to get this to
work, including deriving the template from a non-template class in another
module.  I also tried "extern class A", which compiles but leads to a link
error: 
  "fooFoo.o(.data+0x30): undefined reference to `_D6fooFoo1A7__ClassZ'"
And "extern .fooA.A" does not compile.  (My modules are called fooA and
fooFoo.)  Nothing I've tried works -- except putting everything into the same
module.

In my example, the template calls a static method in A, but even just returning
a reference to A leads to the same compilation error.  In fact, the real cause
seems to be the "import fooA" at the top of 'fooFoo.d'.
Jul 31 2007
next sibling parent BCS <ao pathlink.com> writes:
Reply to C. Dunn,

 I was really hoping to see a response to this.  It's going to prevent
 me from using "D" at all.
I think that there are no blocking problems with this, if you rearrange stuff enough it works (I can't prove this but I haven't ever failed to make things work)
 Because of forward declarations, templates are more flexible in C++. 
As to c++ being more flexible than D, some things might take a bit of work (like what you are looking at), but in all but the most trivial cases c++ can't even hold a candle to D.
 This problem really needs to be addressed.
votes ++; // it is a problem, I agree OTOH this runs, or am I changing something? dmd 1.017 win32 <code name="ModA.d"> |import ModA; | |class Foo(T) |{ | int bar() | { | return A.hi(); | } |}; </code> <code name="ModA.d"> |import ModFoo; |import std.stdio; | |class A{ | static int hi() | { | writef("boo"); | return 0; | } | | Foo!(char) x; |}; | |void main() |{ | A a = new A; | a.x = new typeof(a.x); | a.x.bar(); |} </code>
Jul 31 2007
prev sibling parent BCS <ao pathlink.com> writes:
Reply to C. Dunn,

...
After seeing your bug post, ... DMD has this thing with not doing well with separate compilation. This isn't a big issue because it's so blinking fast. I have a 6125 LOC program that the build script runs a full build 3 times in under 5 sec. So the general advice is to just run everything together.
Jul 31 2007
prev sibling next sibling parent Sean Kelly <sean f4.ca> writes:
C. Dunn wrote:
 This works:
 <code>
 class Foo(T){
   int bar(){
     return A.hi();
   }
 };
 
 class A{
   static int hi(){
     return 0;
   }
 
   F!(char) x;
 };
 </code>
 
 But if I split these into 2 separate modules, where each module imports the
other, then the module with class A does not compile:
   Error: forward reference to 'Foo!(char)'
   Error: F is used as a type
 
 If I make the template class a regular class, it compiles fine.  I understand
that cyclic template specializations could create problems, but I don't see why
moving a template into a separate module fails.  This works easily in C++ by
just forward-declaring class A.
Right. And forward declarations are impossible in D because a type's name includes the module in which it is declared.
 Why does this not work?  Are there plans to support it in the future?
It looks like a compiler bug to me, though who knows when it will be addressed. Sean
Jul 31 2007
prev sibling next sibling parent reply Don Clugston <dac nospam.com.au> writes:
C. Dunn wrote:
 This works:
 <code>
 class Foo(T){
   int bar(){
     return A.hi();
   }
 };
 
 class A{
   static int hi(){
     return 0;
   }
 
   F!(char) x;
 };
 </code>
I presume that should be 'Foo!(char) x;' (even though your error message refers to 'F').
Aug 01 2007
parent C. Dunn <cdunn2001 gmail.com> writes:
Don Clugston Wrote:

 class Foo(T){
 };
 
 class A{
   F!(char) x;
 };
I presume that should be 'Foo!(char) x;' (even though your error message refers to 'F').
Sorry. I had an alias there.
Aug 01 2007
prev sibling next sibling parent reply C. Dunn <cdunn2001 gmail.com> writes:
Kirk McDonald Wrote:

 Goodness. That looks familiar. I used to have all kinds of problems with 
 that in Pyd, but some DMD version or other cleared it all up. Which 
 version of the compiler are you using?
v1.015 How do I download 2.0 for linux?
Aug 01 2007
next sibling parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
C. Dunn wrote:
 Kirk McDonald Wrote:
 
 
Goodness. That looks familiar. I used to have all kinds of problems with 
that in Pyd, but some DMD version or other cleared it all up. Which 
version of the compiler are you using?
v1.015 How do I download 2.0 for linux?
Well, this was pre-1.0. So that's not it. The Linux download is the same as the Windows one. Just be sure you follow the installation instructions to the letter: http://www.digitalmars.com/d/dcompiler.html#linux However, I don't expect the 2.0 series to be any different in this respect. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org
Aug 01 2007
parent reply C. Dunn <cdunn2001 gmail.com> writes:
Kirk McDonald Wrote:

 C. Dunn wrote:
 Kirk McDonald Wrote:
Goodness. That looks familiar. I used to have all kinds of problems with 
that in Pyd, but some DMD version or other cleared it all up. Which 
version of the compiler are you using?
Hey! Do you work on Pyd? Maybe you can answer a question for me: Is the D garbage collector aware of the references in Python to D data? With SWIG, some languages can have problems when the pointer is stored as a string. I just want to be sure that with Pyd it is not mangled somehow to fool the gc. You probably already thought of this, but I just want to be sure. I didn't notice it in the docs. Python is a reference-counted language, so the interaction with a garbage-collector is interesting.
 The Linux download is the same as the Windows one. Just be sure you 
 follow the installation instructions to the letter:
 
 http://www.digitalmars.com/d/dcompiler.html#linux
Yes, but how do I get 2.0 for Linux? I ended up with 1.015.
Aug 01 2007
next sibling parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
C. Dunn wrote:
 Kirk McDonald Wrote:
 
 C. Dunn wrote:
 Kirk McDonald Wrote:
 Goodness. That looks familiar. I used to have all kinds of problems with 
 that in Pyd, but some DMD version or other cleared it all up. Which 
 version of the compiler are you using?
Hey! Do you work on Pyd?
I wrote it. :-)
 Maybe you can answer a question for me:  Is the D garbage collector aware of
the references in Python to D data?
 
 With SWIG, some languages can have problems when the pointer is stored as a
string.  I just want to be sure that with Pyd it is not mangled somehow to fool
the gc.  You probably already thought of this, but I just want to be sure.  I
didn't notice it in the docs.
 
 Python is a reference-counted language, so the interaction with a
garbage-collector is interesting.
 
Pyd keeps references to all items which are returned to Python, until the Python object wrapping the D item is collected, at which time the stored reference is cleared. The D GC does not scan any of the memory allocated by Python, which includes all Python objects. Thus this reference-keeping must be done manually by Pyd. It turns out this is a surprisingly difficult problem to solve correctly, and I've expended quite a lot of effort to get it right.
 
 
 The Linux download is the same as the Windows one. Just be sure you 
 follow the installation instructions to the letter:

 http://www.digitalmars.com/d/dcompiler.html#linux
Yes, but how do I get 2.0 for Linux? I ended up with 1.015.
At the 2.0 changelog: http://digitalmars.com/d/changelog.html Click on the D 2.003 link. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org
Aug 01 2007
prev sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
C. Dunn wrote:
 Kirk McDonald Wrote:
 The Linux download is the same as the Windows one. Just be sure you 
 follow the installation instructions to the letter:

 http://www.digitalmars.com/d/dcompiler.html#linux
Yes, but how do I get 2.0 for Linux? I ended up with 1.015.
http://www.digitalmars.com/d/changelog.html and grab the latest version (link on the version number). -- Daniel
Aug 01 2007
prev sibling parent reply BCS <ao pathlink.com> writes:
Reply to C. Dunn,

 Kirk McDonald Wrote:
 
 Goodness. That looks familiar. I used to have all kinds of problems
 with that in Pyd, but some DMD version or other cleared it all up.
 Which version of the compiler are you using?
 
v1.015 How do I download 2.0 for linux?
I have a script that will install dmd on a linux system (It won't do 2.x but I can fix that without much trouble) you will need root and the authority to install it system wide. http://www.dsource.org/projects/scrapple/browser/trunk/dmd_update/dmd_update
Aug 02 2007
next sibling parent BCS <ao pathlink.com> writes:
Reply to Benjamin,

 Reply to C. Dunn,
 
 Kirk McDonald Wrote:
 
 Goodness. That looks familiar. I used to have all kinds of problems
 with that in Pyd, but some DMD version or other cleared it all up.
 Which version of the compiler are you using?
 
v1.015 How do I download 2.0 for linux?
I have a script that will install dmd on a linux system (It won't do 2.x but I can fix that without much trouble) you will need root and the authority to install it system wide. http://www.dsource.org/projects/scrapple/browser/trunk/dmd_update/dmd_ update
Oh and It's use at your own risk, I think it works but I haven't tested it on many systems yet.
Aug 02 2007
prev sibling parent reply C. Dunn <cdunn2001 gmail.com> writes:
BCS Wrote:

 Reply to C. Dunn,
 
 Kirk McDonald Wrote:
 
 Goodness. That looks familiar. I used to have all kinds of problems
 with that in Pyd, but some DMD version or other cleared it all up.
 Which version of the compiler are you using?
 
v1.015 How do I download 2.0 for linux?
I have a script that will install dmd on a linux system (It won't do 2.x but I can fix that without much trouble) you will need root and the authority to install it system wide. http://www.dsource.org/projects/scrapple/browser/trunk/dmd_update/dmd_update
Cool! I actually already have it working. I just don't know HOW to OBTAIN 2.0 binaries for Linux.
Aug 02 2007
parent BCS <ao pathlink.com> writes:
Reply to C. Dunn,

 BCS Wrote:
 
 Reply to C. Dunn,
 
 Kirk McDonald Wrote:
 
 Goodness. That looks familiar. I used to have all kinds of problems
 with that in Pyd, but some DMD version or other cleared it all up.
 Which version of the compiler are you using?
 
v1.015 How do I download 2.0 for linux?
I have a script that will install dmd on a linux system (It won't do 2.x but I can fix that without much trouble) you will need root and the authority to install it system wide. http://www.dsource.org/projects/scrapple/browser/trunk/dmd_update/dmd _update
Cool! I actually already have it working. I just don't know HOW to OBTAIN 2.0 binaries for Linux.
Oops, I actually sent you a link to a the wrong file here is the good one for whoever is interested http://www.dsource.org/projects/scrapple/browser/trunk/scripts/dmd_update
Aug 02 2007
prev sibling next sibling parent C. Dunn <cdunn2001 gmail.com> writes:
Sean Kelly Wrote:

 It looks like a compiler bug to me, though who knows when it will be 
 addressed.
Problems related to this are getting tougher and tougher to get around. I now compile with all files on one command-line, and that is no longer enough. I have templates in several different files now. If I change the order of .d files on the command-line, I get different messages like this: template instance Foo!(Far) does not match any template declaration I have not been able to reduce the errors to a simple testcase, but I understand the basic problem: D does not have a global view of templates. It needs to remember every template definition that it sees, including specializations, so that it can insert it when requested. This has become a very serious problem and may make it impossible for us to use this language, which I otherwise enjoy very much.
Aug 01 2007
prev sibling next sibling parent C. Dunn <cdunn2001 gmail.com> writes:
Kirk McDonald Wrote:

 ...  but how do I get 2.0 for Linux?  I ended up with 1.015.
At the 2.0 changelog: http://digitalmars.com/d/changelog.html Click on the D 2.003 link.
Thanks, both of you. Now, if I could get 64-bit codegen and better cross-module template support, I'd be a happy Damper.
Aug 02 2007
prev sibling parent Sebastian Beschke <s.beschke gmx.de> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

C. Dunn schrieb:
 This works:
 <code>
 class Foo(T){
   int bar(){
     return A.hi();
   }
 };
 
 class A{
   static int hi(){
     return 0;
   }
 
   F!(char) x;
 };
 </code>
 
 But if I split these into 2 separate modules, where each module imports the
other, then the module with class A does not compile:
   Error: forward reference to 'Foo!(char)'
   Error: F is used as a type
 
 If I make the template class a regular class, it compiles fine.  I understand
that cyclic template specializations could create problems, but I don't see why
moving a template into a separate module fails.  This works easily in C++ by
just forward-declaring class A.
 
 Why does this not work?  Are there plans to support it in the future?
Does anyone know if this problem has been resolved in the meantime? I'm having similar error messages with all my templates after upgrading rebuild. Is that an old problem or a new problem? Sebastian -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFHLPWgKb/1n5A2TAMRApWeAJ433N8pE4nrArZBmFqEuUwuAM+RHgCfXn7S d16Ay3HwzepN52b8AdImLU0= =yzOF -----END PGP SIGNATURE-----
Nov 03 2007