www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Forward declaration issue

reply Andre <andre s-e-a-p.de> writes:
Hi,

I have a strange issue with following coding.

void baz(); // forward declaration

void foo()
{
	void bar()
	{
		baz(); // (1) without f.d. syntax error
	}
	
	void baz()
	{
		bar();
	}
	
	baz(); // (2) No linker error if line is removed
}

void main()
{
	foo();
}

Without the forward declaration, there is a syntax error at (1)
With the forward declaration there is no syntax error but
a linker error at (2). This linker error disappears if line at (2)
is removed.
It looks like a bug, is it?

Kin regards
Andre
Dec 04 2015
next sibling parent Jonathan M Davis via Digitalmars-d-learn writes:
On Friday, December 04, 2015 08:12:05 Andre via Digitalmars-d-learn wrote:
 Hi,

 I have a strange issue with following coding.

 void baz(); // forward declaration

 void foo()
 {
   void bar()
   {
       baz(); // (1) without f.d. syntax error
   }

   void baz()
   {
       bar();
   }

   baz(); // (2) No linker error if line is removed
 }

 void main()
 {
   foo();
 }

 Without the forward declaration, there is a syntax error at (1)
 With the forward declaration there is no syntax error but
 a linker error at (2). This linker error disappears if line at (2)
 is removed.
 It looks like a bug, is it?
You cannot use symbols before you declare them in a function (even if they're nested functions), and you can't forward declare them. When you declare baz outside of foo, bar is now trying to use a different baz from the one that you declare after it. Rather, it's trying to use one that's at the module-level, not a nested function. And you never defined that baz. So, you get a linker error when you use it. What's going on would be clearer if you used distinct names: void module_baz(); void foo() { void bar() { module_baz(); } void baz() { bar(); } baz(); } While that may not be what you're trying to do, it's what you're actually doing. Mutually recursive nested functions aren't possible in D. - Jonathan M Davis
Dec 04 2015
prev sibling parent reply Artur Skawina via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On 12/04/15 09:12, Andre via Digitalmars-d-learn wrote:
 Hi,
 
 I have a strange issue with following coding.
 
 void baz(); // forward declaration
 
 void foo()
 {
     void bar()
     {
         baz(); // (1) without f.d. syntax error
     }
     
     void baz()
     {
         bar();
     }
     
     baz(); // (2) No linker error if line is removed
 }
 
 void main()
 {
     foo();
 }
 
 Without the forward declaration, there is a syntax error at (1)
 With the forward declaration there is no syntax error but
 a linker error at (2). This linker error disappears if line at (2)
 is removed.
 It looks like a bug, is it?
No, it's how D is designed -- inside functions the order of declarations matters (and forward declarations don't work). Your version wrongly declares another `baz` at module scope, and, as there's no definition, you end up with the linker error. Two workarounds: 1) Templatize the functions: void foo() { void bar()() { baz(); } void baz()() { bar(); } baz(); } 2) Use a struct: void foo() { struct Hack { void bar() { baz(); } void baz() { bar(); } } Hack hack; hack.baz(); } artur
Dec 04 2015
parent Andre <andre s-e-a-p.de> writes:
On Friday, 4 December 2015 at 09:51:30 UTC, Artur Skawina wrote:

 No, it's how D is designed -- inside functions the order of 
 declarations matters (and forward declarations don't work).

 Your version wrongly declares another `baz` at module scope, 
 and, as there's no definition, you end up with the linker error.

 Two workarounds:

 1) Templatize the functions:

    void foo()
    {
       void bar()()
       {
           baz();
       }

       void baz()()
       {
           bar();
       }

       baz();
    }

 2) Use a struct:

    void foo()
    {
       struct Hack {
          void bar()
          {
              baz();
          }

          void baz()
          {
              bar();
          }
       }

       Hack hack;

       hack.baz();
    }

 artur
Thanks for the clarifications and the example. Kind regards André
Dec 04 2015