Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error: incomplete type used in nested name specifier

Tags:

c++

g++

There are 2 non-template classes A, B having some static template methods.

From class A static method in B is called and from class B static method from A is called. The source code only for illustration (not real code)...

A.h

#include "B.h"
class A 
{
 public:
   template <class T>
   void f1 ()
   {
      T var1= ...;
      T var2 = B::f4(T);
   }

   template <class T>
   T f2()
   {
      return ...
   }
};

#include "A.h"
class B
{
 public:
   template <class T>
   void f3 ()
   {
      T var1= ...;
      T var2 = A::f2(T); //Error
   }

   template <class T>
   T f4()
   {
      return ...
   }
};

I am having troubles with g++ compiler in NetBeans. During the compilation the following error occurs: Error: incomplete type A used in nested name specifier, g++.

I tried to add forward declarations into both classes, but nothing was successful.

There is an older bug:

http://gcc.gnu.org/ml/gcc-bugs/2005-02/msg01383.html

like image 229
Ian Avatar asked Dec 31 '10 21:12

Ian


2 Answers

You have a circular dependency between your header files. Since your classes are so tightly intertwined, I'd suggest merging them into a single header file, structured like this:

class A
{
public:
  template <class T>
  void f1();
};

class B
{
  ...
};

template <class T>
void A::f1()
{
  // Use full definition of class B
}

If you insist on using separate header files for A and B (which won't really make any difference since they end up including each other), you'll need to restructure them so that one of the headers doesn't include the other, so at least one of the dependent template functions will need to be defined in a separate file. For example:

// File "a_no_b.h"
class A
{
public:
  template <typename T>
  void f1();
};

// File "b_no_a.h"
class B
{
public:
  template <typename T>
  void f3();
};

// File "a.h"
#include "a_no_b.h"
#include "b_no_a.h"

template <typename T>
void A::f1()
{
  // Use full definition of class B
}

// File "b.h"
#include "b_no_a.h"
#include "a_no_b.h"

template <typename T>
void B::f3()
{
  // Use full definition of class A
}
like image 140
Adam Rosenfield Avatar answered Nov 06 '22 16:11

Adam Rosenfield


Because there is a circular dependency, you need to carefully arrange the declarations of classes A and B so that they are both declared before the member functions are defined.

Here is A.h:

#ifndef A_H
#define A_H 1
class A 
{
 public:
     template <class T>
     void f1 ();

     template <class T>
     T f2();
};

#include "B.h"

template <class T>
void A::f1()
{
     T var1= ...;
     T var2 = B::f4(T);
}

template <class T>
T A::f2()
{
     return ...
}

#endif

Here is B.h:

#ifndef B_H
#define B_H 1
class B
{
 public:
     template <class T>
     void f3 ();

     template <class T>
     T f4();
};

#include "A.h"

template <class T>
void B::f3()
{
     T var1= ...;
     T var2 = A::f2(T);
}

template <class T>
T B::f4()
{
     return ...
}

#endif

With this approach, you will be able to include either A.h or B.h first and not have a problem.

like image 26
Daniel Trebbien Avatar answered Nov 06 '22 14:11

Daniel Trebbien