Thread overview
Forward declaration issue
Dec 04, 2015
Andre
Dec 04, 2015
Jonathan M Davis
Dec 04, 2015
Artur Skawina
Dec 04, 2015
Andre
December 04, 2015
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
December 04, 2015
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

December 04, 2015
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
December 04, 2015
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é