C++ 没有可用于具有初始值设定项的静态常量成员的定义?
鉴于:C++ 没有可用于具有初始值设定项的静态常量成员的定义?,c++,templates,c++11,instantiation,C++,Templates,C++11,Instantiation,鉴于: 模板 结构{ 静态int常数N=1; }; 外部模板类; 模板 int f(T n){ 返回n+S::n;//第10行 } int main(){ 返回f(1);//第14行 } //模板类S;//故意注释掉以触发错误 我得到: template<class T> struct S { static int const N = 1; }; extern template class S<int>; template<class T> int
模板
结构{
静态int常数N=1;
};
外部模板类;
模板
int f(T n){
返回n+S::n;//第10行
}
int main(){
返回f(1);//第14行
}
//模板类S;//故意注释掉以触发错误
我得到:
template<class T>
struct S {
static int const N = 1;
};
extern template class S<int>;
template<class T>
int f( T n ) {
return n + S<T>::N; // line 10
}
int main() {
return f(1); // line 14
}
//template class S<int>; // intentionally commented out to trigger error
foo.cpp:intf(T)[with T=int]函数中:
foo.cpp:10:从“const int S::N”实例化
foo.cpp:10:从“intf(T)[带T=int]实例化”
foo.cpp:14:从这里实例化
foo.cpp:10:错误:“S::N”的显式实例化,但没有可用的定义
但是为什么我会得到错误
S::N
extern模板类;
foo.cpp: In function ‘int f(T) [with T = int]’:
foo.cpp:10: instantiated from ‘const int S<int>::N’
foo.cpp:10: instantiated from ‘int f(T) [with T = int]’
foo.cpp:14: instantiated from here
foo.cpp:10: error: explicit instantiation of ‘S<int>::N’ but no definition available
我认为这行代码会导致错误,因为它告诉编译器在某处查找S
的显式实例化,但不存在显式实例化。因此出现了错误
一旦你注释了这一行,我认为代码应该编译得很好
编辑: 那么看这个, 正如我所说,它编译得很好
编辑: 我认为$9.4.2/4(由Mark B引用)不适用于类模板的静态成员,因为$14.5.1.3[temp.static]不要求在命名空间范围内定义静态成员: 静态数据成员的定义 可以在命名空间范围中提供 包含静态的定义 成员的类模板 下面的例子是:
extern template class S<int>;
模板类X{static ts;};
模板tx::s=0;
注意,它没有说“必须提供”,而是说“可能提供”。因此,我认为在命名空间范围内定义类模板的静态成员是可选的。来自9.4.2/2:
静态数据的声明
其类定义中的成员不是
一个定义,可以是
不完整的类型,但不符合条件
无效的静态数据的定义
成员应出现在名称空间中
包含成员类的范围
定义。在
命名空间范围,名称空间的名称
静态数据成员应是合格的
通过其类名使用::
接线员
从9.4.2/4开始:
如果静态数据成员为常量
整型或常量枚举类型,
它在课堂上的声明
定义可以指定
康斯坦丁化剂,应为
积分常数表达式(5.19)。
在这种情况下,成员可以出现在
内的积分常数表达式
它的范围。该成员仍应为
在命名空间范围中定义,如果
在程序和命名空间中使用
范围定义不应包含
初始化器
从这些引用中,我们可以推断(“…仍应定义…”在9.4.2/4)中,如果未定义,则程序的格式不正确。您可以使用
enum{N=1}
而不是静态常量
@KennyTM:这并不能回答问题。显然,这个例子是我真实代码的一个缩减的例子。真正的代码需要一个unsigned long集,设置为~0,而且,恕我直言,枚举不能是“unsigned”的。我认为这只是一个编译器错误。它在mingw下用g++4.4.0编译的很好。我觉得这是个编译器问题。Comeau和VC++似乎没有任何问题(尽管如果你取消注释最后一行,VC++抱怨该实例化没有extern
,因此它与前一行不匹配。你也可以将其解释为“可能提供”与“可能根本不提供”,而不是相反的意思“可能在其他地方提供”。该标准是否允许在其他地方提供?@Oli:我将其解释为“可能根本不提供”。我的意思是,命名空间范围中的定义是可选的。
template<class T> class X { static T s; };
template<class T> T X<T>::s = 0;