In C++, one does ? for circular dependencies?

Discussion of chess software programming and technical issues.

Moderator: Ras

CRoberson
Posts: 2094
Joined: Mon Mar 13, 2006 2:31 am
Location: North Carolina, USA

In C++, one does ? for circular dependencies?

Post by CRoberson »

I have coded a solution to a speed issue for Telepath that should
produce a 30% speed improvement. However, it doesn't compile.
I looked through over 100 pages of C++ book and didn't find a
hint of a solution. So, who knows the answer to the following problem
that is quite easily resolved in C.

Code: Select all

   Class X
   {
      private:
      public:
         int G( Y &t);
    };

    Class Y
    {
         private:
         public:
           int C( X &m);
    };

If these were functions in C, I'd set an empty prototype for Y ahead
of X.

I literally went though more than 100 pages of a C++ manual
on its how to do classes and found nothing.
Any C++ expert know this one?
Rein Halbersma
Posts: 751
Joined: Tue May 22, 2007 11:13 am

Re: In C++, one does ? for circular dependencies?

Post by Rein Halbersma »

CRoberson wrote:I have coded a solution to a speed issue for Telepath that should
produce a 30% speed improvement. However, it doesn't compile.
I looked through over 100 pages of C++ book and didn't find a
hint of a solution. So, who knows the answer to the following problem
that is quite easily resolved in C.

Code: Select all

   Class X
   {
      private:
      public:
         int G( Y &t);
    };

    Class Y
    {
         private:
         public:
           int C( X &m);
    };

If these were functions in C, I'd set an empty prototype for Y ahead
of X.

I literally went though more than 100 pages of a C++ manual
on its how to do classes and found nothing.
Any C++ expert know this one?
change "Class" to "class" and precede the fragment with "class Y;" (forward declaration).
CRoberson
Posts: 2094
Joined: Mon Mar 13, 2006 2:31 am
Location: North Carolina, USA

Re: In C++, one does ? for circular dependencies?

Post by CRoberson »

The forward declaration methodology fixed it. I didn't have class capitalized in my code.

The new code is much faster. My perft performance went from 935 Knps to 2205 Knps.
User avatar
Desperado
Posts: 879
Joined: Mon Dec 15, 2008 11:45 am

Re: In C++, one does ? for circular dependencies?

Post by Desperado »

maybe dependent on compiler, but generally you have to do this:


Code: Select all

 //DECLARATION !!!
 class X;
 class Y;

 //DEFINITION !!!
 class X 
   { 
      private: 
      public: 
         int G( Y &t); 
    }; 

    class Y 
    { 
         private: 
         public: 
           int C( X &m); 
    }; 

void main (void)
	{
	}
now there shouldnt be a compiler error with a message "unknown" type or something like this...
Rein Halbersma
Posts: 751
Joined: Tue May 22, 2007 11:13 am

Re: In C++, one does ? for circular dependencies?

Post by Rein Halbersma »

Desperado wrote:maybe dependent on compiler, but generally you have to do this:


Code: Select all

 //DECLARATION !!!
 class X;
 class Y;

 //DEFINITION !!!
 class X 
   { 
      private: 
      public: 
         int G( Y &t); 
    }; 

    class Y 
    { 
         private: 
         public: 
           int C( X &m); 
    }; 

void main (void)
	{
	}
now there shouldnt be a compiler error with a message "unknown" type or something like this...
On a decent C++ compiler, you will get a warning (if not an error) for using "void main(void)" rather than "int main(void)"...
User avatar
Desperado
Posts: 879
Joined: Mon Dec 15, 2008 11:45 am

Re: In C++, one does ? for circular dependencies?

Post by Desperado »

Hi Rein, maybe ... overread this, the problem to solve was the
"declaration problem", i just use it in my testcode to be able to compile...

maybe dependent on compiler, but generally you have to do this:


Code: Select all

  //DECLARATION !!!
 //class X; should be declared
 class Y; //has to be declared so class X know class Y

 //now ! DEFINITION !!!
 class X 
   { 
      private: 
      public: 
         int G( Y &t); 
    }; 

    class Y 
    { 
         private: 
         public: 
           int C( X &m); 
    }; 

// somewhere a kind of main function
// only this kind for ex:
void main (void)
	{
	}
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: In C++, one does ? for circular dependencies?

Post by mcostalba »

Desperado wrote:Hi Rein, maybe ... overread this, the problem to solve was the
"declaration problem", i just use it in my testcode to be able to compile...

maybe dependent on compiler, but generally you have to do this:


Code: Select all

  //DECLARATION !!!
 //class X; should be declared
 class Y; //has to be declared so class X know class Y

 //now ! DEFINITION !!!
 class X 
   { 
      private: 
      public: 
         int G( Y &t); 
    }; 

    class Y 
    { 
         private: 
         public: 
           int C( X &m); 
    }; 

// somewhere a kind of main function
// only this kind for ex:
void main (void)
	{
	}

Ok. Not to be pedantic, but because you are looking at the small details then you should change this:

DECLARATION --> FORWARD DECLARATION

DEFINITION --> DECLARATION

A class method definition is when you write:

int X::G( Y &t) { ....... }

So I would rewrite like this:

Code: Select all


struct Y; // forward declaration


struct X  // class declaration
{ 
    int G( Y &t); 
}; 

struct Y 
{ 
    int C( X &m); 
};

int X::G( Y &t)  {  ....... } // method definition
 

// main function
int main(int argc, char* argv[])
{

}

What you call "class X declaration", actually a forward declaration, is not needed in any way.
User avatar
Bo Persson
Posts: 262
Joined: Sat Mar 11, 2006 8:31 am
Location: Malmö, Sweden
Full name: Bo Persson

Re: In C++, one does ? for circular dependencies?

Post by Bo Persson »

mcostalba wrote:
Desperado wrote:Hi Rein, maybe ... overread this, the problem to solve was the
"declaration problem", i just use it in my testcode to be able to compile...

maybe dependent on compiler, but generally you have to do this:


Code: Select all

  //DECLARATION !!!
 //class X; should be declared
 class Y; //has to be declared so class X know class Y

 //now ! DEFINITION !!!
 class X 
   { 
      private: 
      public: 
         int G( Y &t); 
    }; 

    class Y 
    { 
         private: 
         public: 
           int C( X &m); 
    }; 

// somewhere a kind of main function
// only this kind for ex:
void main (void)
	{
	}

Ok. Not to be pedantic, but because you are looking at the small details then you should change this:

DECLARATION --> FORWARD DECLARATION

DEFINITION --> DECLARATION

A class method definition is when you write:

int X::G( Y &t) { ....... }

So I would rewrite like this:

Code: Select all


struct Y; // forward declaration


struct X  // class declaration
{ 
    int G( Y &t); 
}; 

struct Y 
{ 
    int C( X &m); 
};

int X::G( Y &t)  {  ....... } // method definition
 

// main function
int main(int argc, char* argv[])
{

}

What you call "class X declaration", actually a forward declaration, is not needed in any way.
No, the C++ language only has declaration (introducing the name) and definition (telling exactly what the name means).

In this case we have a declaration of that class names, followed by a definition of the class itself. That the class member functions are defined outside the class body doesn't change this.

Calling the declaration a forward declaration is ok, but a class definition is always a definition. It doesn't matter if the member functions are defined inside the class, elsewhere in the same file, or even in another file.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: In C++, one does ? for circular dependencies?

Post by Sven »

From the C++ standard (new draft 2008 directly from Bjarne Stroustrup's page):
3.1 Declarations and definitions

1 A declaration (Clause 7) introduces names into a translation unit or redeclares names introduced by previous declarations. A declaration specifies the interpretation and attributes of these names.

2 A declaration is a definition unless it declares a function without specifying the function’s body (8.4), it contains the extern specifier (7.1.1) or a linkage-specification (7.5) and neither an initializer nor a functionbody, it declares a static data member in a class definition (9.4), it is a class name declaration (9.1), it is an opaque-enum-declaration (7.2), or it is a typedef declaration (7.1.3), a using-declaration (7.3.3), or a using-directive (7.3.4).
So a "class declaration" and a "class definition" are the same in C++, while what we also refer to as "forward declaration" of a class is called "class name declaration" by the standard.

Back to the original problem, in general I would also prefer to only add one of the two class name declarations, "class Y;", since that is the one that is required by the "class X { ... }" definition that uses Y, while the definition of Y follows after X has already been fully defined.

Nevertheless, the "real world" sometimes is different, you may end up in putting the two class definitions each into separate header files (if they grow, or course), and then it is good style to always add class name declarations for classes that are used by reference or by pointer within the class definition. In such a case one should not try to predict the order in which these header files will be read by the compiler, maybe the order will even be different for different translation units. So "x.h" would have "class Y; class X { ... /* uses Y by reference */ };" and "y.h" "class X; class Y { ... /* uses X by reference */ };".

Sven
User avatar
Desperado
Posts: 879
Joined: Mon Dec 15, 2008 11:45 am

Re: In C++, one does ? for circular dependencies?

Post by Desperado »

Funny (a little bit) the thread here :-).

We are back to the roots :-)

But talking about such basics i would like to add my statement once
again:

For me:

- a Declaration (doesnt matter c / c++ elsewhere) just
lets the compiler know that there is existing something(a type,class whatever).if this content is given it is a declaration. Sometimes it is two in one a Declaration and the next, a Definition.

- a Definition for me is when you let the compiler know how the type/class
looks like.(so this can(must not) be done with a declaration).

- and then of course the instances... (without comment)

So, for me doesnt exist a so called "Forward Declaration". The only thing
to differ if declartion and definition is a "2 in 1 statement" or both of them are seperate instructions (if you want to call this "seperate" -> "Forward Declaration" thats ok, but doesnt change the contents, and because it doesnt change the contents you can simple call it "declaration").
(Also the word declaration (in my eyes) cant be done twice. if it declared it's declared, or not ?)

Does anybody disagree ? (Hope not :-) )