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

看起来编译器抱怨“必须在使用前声明显式特化“类 A::B”。” 如果我尝试在注释行中提供 froward 声明,编译器会抱怨“必须在包含模板的命名空间中声明显式特化“B”。” 我们在这里使用 2 种不同的编译器。这个错误来自 IBM 在 AIX 上的“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 不是模板类,您正在尝试专门化它。这就是错误的原因。您可以检查这两个错误C2913C3413。这是你想要的?

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