3

これをまったくコンパイルできません。できないかもしれませんが、なぜできないのかわかりません。

class A {
  template <typename T> 
  class B {
   int test() { return 0; }
  };
  //template <> class B<int>; <-with this, namepace error
  B<int> myB_;
 };

 template <> class A::B<int> {
  int test() {
   return 1;
  }
 };

コンパイラは、「明示的な特殊化 "class A::B" は、使用する前に宣言する必要があります」と不平を言っているようです。コメント行で前方宣言を提供しようとすると、コンパイラは「明示的な特殊化 "B" は、テンプレートを含む名前空間で宣言する必要があります」と文句を言います。ここでは 2 つの異なるコンパイラを使用します。このエラーは、AIX 上の IBM の "xl" コンパイラによるものですが、Sun システムでコンパイルすると、異なる表現で同様のエラーが発生します。キャッチ22のようです。

明らかに、これは非常に不自然で単純化された例ですが、問題を表しています。テンプレート クラスはそれを含むクラスにのみ関連するため、クラス内でテンプレート クラスを定義したいと考えています。クラス外からテンプレートにアクセスすることはできません。

何か不足していますか?

4

3 に答える 3

3

あなたは正しいです。これはできません(私の知る限り)。メンバー宣言は、明示的な特殊化が宣言される前に暗黙的なインスタンス化を引き起こします。しかし、どのように宣言したいですか?クラススコープでそれを行うことはできません。これは醜い制限だと感じている人もいます。

クラスメンバーをポインターにすることで、これを回避できます。これは、その時点でクラスを暗黙的にインスタンス化する必要はなく、最終的にオブジェクトを作成する時点でインスタンス化する必要があります。これは醜い回避策であることを理解しています。したがって、これを行う他の方法を見つけたほうがよいでしょう。

たとえば、部分的な特殊化はクラス スコープで許可されます。したがって、ダミーのテンプレート パラメーターを追加して、メンバー宣言の前にクラスでこれを特殊化できます。同様に、これは醜いと思いますが、それほど邪魔にはならないと思います。

于 2010-09-03T13:04:03.423 に答える
0

プライバシーのために名前のない名前空間を使用することで、この問題を回避できます。

namespace {

  template <typename T> 
  class B {
   int test() { return 0; }
  };

  template <> class B<int> {
    int test() {
      return 1;
    }
};

}

class A {
  B<int> myB_;
};

これはコンパイルされますが、Aこのコンパイル ユニットの外部で表示する必要がある場合は、より複雑な機構 (たとえば、インターフェイスとファクトリまたはPimpl ) が必要になります。

于 2010-09-03T13:13:04.443 に答える
0

B はテンプレート クラスではなく、特殊化しようとしています。それがエラーの原因です。これら 2 つのエラーC2913およびC3413を確認できます。これはあなたが探しているものですか?

class A
{
   template<class T>
   class B
   {
      inline int test()
      {
         return 0;
      }
   };
   A::B<int> myB_;
};
于 2010-09-03T13:13:26.730 に答える