Ошибка: неполный тип используется в спецификаторе вложенного имени - PullRequest
19 голосов
/ 01 января 2011

Есть 2 не шаблонных класса A, B, имеющих несколько статических методов шаблона.

Из класса A вызывается статический метод в B, а из класса B вызывается статический метод из A. Исходный код только для иллюстрации (не настоящий код) ...

хиджры

#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 ...
   }
};

У меня проблемы с компилятором g ++ в NetBeans. Во время компиляции возникает следующая ошибка: Ошибка: неполный тип A, используемый в описателе вложенного имени, g ++.

Я пытался добавить предварительные объявления в оба класса, но ничего не получилось.

Существует старая ошибка:

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

Ответы [ 3 ]

7 голосов
/ 01 января 2011

У вас есть круговая зависимость между вашими заголовочными файлами.Поскольку ваши классы так тесно переплетены, я бы предложил объединить их в один заголовочный файл, структурированный так:

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

class B
{
  ...
};

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

Если вы настаиваете на использовании отдельных заголовочных файлов для A и B (что не будетдействительно имеют какое-то значение, так как они в конечном итоге включают друг друга), вам нужно реструктурировать их так, чтобы один из заголовков не включал другой, поэтому по крайней мере одну из зависимых функций шаблона нужно будет определить в отдельномфайл.Например:

// 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
}
4 голосов
/ 01 января 2011

Поскольку существует циклическая зависимость, вам нужно тщательно упорядочить объявления классов A и B, чтобы они оба были объявлены до определения функций-членов.

Вот 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

Вот 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

При таком подходе вы сможете сначала включить A.h или B.h и не иметь проблем.

0 голосов
/ 01 января 2011

Ваша проблема - зависимость от кругового заголовка.

...