为模板特化初始化静态常量
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;
您代码中的 C1
和 C2
不是 C
的完全特化,而是 C
的特化的 classes .所以我不知道你在这里期待什么...
我创建了一个带有静态 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;
您代码中的 C1
和 C2
不是 C
的完全特化,而是 C
的特化的 classes .所以我不知道你在这里期待什么...