假设:
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: 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<T>::N
。这适用于Mac OS X 10.6.6上的g ++ 4.2.1。
答案 0 :(得分:2)
extern template class S<int>;
我认为这一行会导致错误,因为它告诉编译器在某处查找S<int>
的显式实例化,但不存在显式实例化。因此错误。
一旦你评论这一行,我认为代码应该编译好。
编辑:
好吧,请看:http://www.ideone.com/oQnOi
正如我所说,它编译得很好!
编辑:
我认为$ 9.4.2 / 4(由 Mark B 引用)不适用于类模板的静态成员,因为$ 14.5.1.3 [temp。 static]不强制在命名空间范围内定义静态成员:
静态数据成员的定义 可以在命名空间范围中提供 包含静态的定义 会员的班级模板。
示例如下,
template<class T> class X { static T s; };
template<class T> T X<T>::s = 0;
注意,它没有说“必须提供”,而是“可能提供”。所以我认为在命名空间范围内类模板的静态成员的定义是可选的。
答案 1 :(得分:2)
从9.4.2 / 2开始:
静态数据的声明 其类定义中的成员不是 一个定义,可能是一个 除了cvqualified之外的不完整类型 无效。静态数据的定义 成员应出现在命名空间中 封闭成员类的范围 定义。在定义中 命名空间范围,名称 静态数据成员应具备资格 通过其类名使用:: 操作
从9.4.2 / 4:
如果静态数据成员是const 整数或常数枚举类型, 它在课堂上的宣言 定义可以指定一个 constantinitializer是一个 积分常数表达式(5.19)。 在这种情况下,该成员可以出现在 内积分常数表达式 它的范围。该成员仍然是 如果是,则在命名空间范围内定义 用于程序和命名空间 范围定义不得包含 初始化程序。
根据这些参考文献,我们可以推断(“......仍然应该在9.4.2 / 4中定义......”)如果没有定义那么程序就没有格式良好。