views:

49

answers:

3

I can't get this to compile at all. I may not be possible but I don't know why it should not be.

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

As it appears the compiler complains "The explicit specialization "class A::B" must be declared before it is used." If I try to provide the froward declaration in the commented line, the compiler complains "The explicit specialization "B" must be declared in the namespace containing the template." We use 2 different compilers here. This error is from IBM's "xl" compiler on AIX but I get similar errors with different verbage when compiling on our Sun systems. It seems like a catch-22.

Obviously, this is a highly contrived, simplistic example but, it represents the problem. I want to define a template class within a class because the template class is only relevent to the containing class. There should be no access to the template from outside the class.

Am I missing something?

+3  A: 

You are correct. This is not possible to do (as far as I know). Your member declaration causes an implicit instantiation before the explicit specialization was declared. But how would you want to declare it? You cannot do that in class scope. Others have felt that this is an ugly restriction.

You could work around this by making the class member a pointer. This would not need to implicitly instantiate the class at that point, but rather at the point where you create the object in the end. I realize that this is an ugly work around. So better find other ways to do this.

For instance partial specializations are allowed in class scope. So you could add a dummy template parameter, then you can specialize this in the class before the member declaration. Likewise, i find this ugly, but it would not disturb things that much, I feel.

Johannes Schaub - litb
A: 

You could work around the issue by using an unnamed namespace for privacy:

namespace {

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

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

}

class A {
  B<int> myB_;
};

This will compile, but if A needs to be visible outside this compilation unit, you'll need more elaborate machinery (e.g., interface and factory or Pimpl).

Greg Bacon
A: 

B is not a template class and you are trying to specialize it. That is the cause for the error. You can check these two errors C2913 and C3413. Is this what you are looking for?

class A
{
   template<class T>
   class B
   {
      inline int test()
      {
         return 0;
      }
   };
   A::B<int> myB_;
};
Gangadhar
Sorry, realized that this is not what @user438938 was asking for. Misunderstood the question.
Gangadhar