user3065699
user3065699

Reputation: 329

Initializing a static const for a template specialization

I have created a class template with a static const element. The intent is for each specialization of the template to have its own version / value of this static element. Here is my sample code:

template < typename T > class C
{
   public:
      static const std::string NAME;
      T something;
      void printName() { std::cout << NAME << std::endl; }
};

class C1 : public C< int >{};
class C2 : public C< char >{};

template<> const std::string C< int >::NAME{ "my int" };   // compiles
template<> const std::string C< char >::NAME{ "my char" }; // compiles

//template<> const std::string C1::NAME{ "my int" };   // doesn't compile
//template<> const std::string C2::NAME{ "my char" };  // doesn't compile

//const std::string C1::NAME{ "my int" };   // doesn't compile
//const std::string C2::NAME{ "my char" };  // doesn't compile

int main()
{
   C1 c1;
   C2 c2;

   c1.printName();
   c2.printName();

   std::cout << c1.NAME << "  " << c2.NAME << std::endl;
   std::cout << C1::NAME << "  " << C2::NAME << std::endl;
}

When using the compilable version, the output is what I would expect:

my int
my char
my int  my char
my int  my char

For the lines that don't compile, the error message (using gcc 4.4) says

ISO C++ does not permit 'C<int>::NAME' to be defined as 'C1::NAME'

Why is this not permitted? My understanding is that a full specialization of a template is a class in all (?) respects, and this class has all the members declared in the template. So I would expect to be able to refer to static members of that class by using a scope resolution operator. Apparently I can do so after the initialization, as in the last line of main above, but not in the initialization itself.

Can anyone provide any insight as to why the standard was written this way? What kind of problems would arise if the standard allowed the 'bad' syntax above?

Upvotes: 2

Views: 852

Answers (1)

Brian Bi
Brian Bi

Reputation: 119219

It looks to me like the problem you're encountering has nothing to do with templates. The problem is that you're trying to define a static member using a derived class in the nested-name-specifier, not the original class. You would have the same issue here:

struct A {
    static int x;
};
struct B : A{};
int B::x = 42;

The C1 and C2 in your code are not full specializations of C, rather, they are derived classes of specializations of C. So I don't know what you're expecting here...

Upvotes: 3

Related Questions