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?

Famous Bug #340 and especially #102.
Jul 31 2007
parent reply C. Dunn <cdunn2001 gmail.com> writes:
Witold Baryluk Wrote:
 Famous Bug #340 and especially #102.

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 to #805 and #877, but I have submitted it as #1392. (I read all 21 bugs related to #340.) 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:
 
Famous Bug #340 and especially #102.

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 to #805 and #877, but I have submitted it as #1392. (I read all 21 bugs related to #340.) 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 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