初始化模板专门化的静态const

Initializing a static const for a template specialization

本文关键字:静态 const 专门化 初始化      更新时间:2023-10-16

我创建了一个带有静态const元素的类模板。这样做的目的是让模板的每个专门化都拥有这个静态元素的自己的版本/值。下面是我的示例代码:

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

当使用可编译版本时,输出是我期望的:

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

对于不能编译的行,错误信息(使用gcc 4.4)显示

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

为什么不允许?我的理解是,模板的完整专门化在所有方面都是一个类,这个类具有模板中声明的所有成员。因此,我希望能够通过使用作用域解析操作符来引用该类的静态成员。显然,我可以在初始化之后这样做,就像上面main的最后一行一样,但不能在初始化本身中这样做。

谁能解释一下为什么标准是这样写的?如果标准允许上面的"坏"语法,会出现什么样的问题?

在我看来,你遇到的问题与模板无关。问题是,您试图使用嵌套名称说明符中的派生类(而不是原始类)定义静态成员。你在这里也会遇到同样的问题:

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

代码中的C1C2不是C的完全专门化,而是C专门化的派生类。所以我不知道你在期待什么