为模板特化初始化静态常量

Initializing a static const for a template specialization

我创建了一个带有静态 const 元素的 class 模板。目的是让模板的每个特化都有自己的静态元素版本/值。这是我的示例代码:

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'

为什么不允许这样做?我的理解是,模板的完全特化在所有 (?) 方面都是 class,并且此 class 具有模板中声明的所有成员。所以我希望能够通过使用范围解析运算符来引用 class 的静态成员。显然我可以在初始化之后这样做,就像上面 main 的最后一行一样,但不能在初始化本身中这样做。

任何人都可以提供任何关于为什么以这种方式编写标准的见解吗?如果标准允许上面的 'bad' 语法会出现什么样的问题?

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

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

您代码中的 C1C2 不是 C 的完全特化,而是 C 的特化的 classes .所以我不知道你在这里期待什么...