web-dev-qa-db-ja.com

エラー:ネストされた名前指定子で不完全な型が使用されています

いくつかの静的テンプレートメソッドを持つ2つの非テンプレートクラスABがあります。

クラス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 ...
   }
};

NetBeansのg ++​​コンパイラに問題があります。コンパイル中に次のエラーが発生します。エラー:ネストされた名前指定子で使用される不完全なタイプA、g ++。

両方のクラスに前方宣言を追加しようとしましたが、何も成功しませんでした。

古いバグがあります:

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

19
Ian

ヘッダーファイル間に循環依存関係があります。クラスは密接に絡み合っているので、次のような構造の単一のヘッダーファイルにマージすることをお勧めします。

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

class B
{
  ...
};

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

AとBに別々のヘッダーファイルを使用することを主張する場合(それらが最終的にお互いを含むため、実際には違いはありません)、ヘッダーの1つに他が含まれないように再構成する必要があります。したがって、依存するテンプレート関数の少なくとも1つを別のファイルで定義する必要があります。例えば:

// 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
}
7
Adam Rosenfield

循環依存があるため、クラス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最初に問題はありません。

4
Daniel Trebbien

あなたの問題は循環ヘッダー依存です。

0
Gene Bushuyev