【发布时间】:2014-03-17 18:21:05
【问题描述】:
我一直在玩 gcc 4.8.2 中的模板类和常量,遇到了一个有趣的链接器错误:
#include <iostream>
using namespace std;
template <class T, int m>
class A {
public:
static const T param = m;
T value;
A(const T &value, const T &dummy = T()) : value(value) {}
};
// Works with this
// template <class T, int m>
// const T A<T, m>::param = m;
template <class T, int m>
A<T, m> operator +(const A<T, m> &a, const A<T, m> &b) {
if (a.param != b.param) exit(1);
// Works if I replace a.param with 0
return A<T, m>(a.value + b.value, a.param);
}
int main() {
A<int, 2> v = A<int, 2>(1) + A<int, 2>(2);
cout << v.value << endl;
return 0;
}
在当前状态下编译代码会出现链接器错误,告诉我A::param 未定义。
在 Visual Studio 2008 中也尝试此代码,它编译和链接没有任何问题。在 gcc 上,当我使用 param 常量的外部声明,或者如果我将 a.param 替换为 0 或在指示的行上没有任何内容时,它会编译。
我不明白的是为什么包含if 语句的行可以使用a.param 而不会出现编译错误,而我不能在没有外部声明的情况下将a.param 传递给构造函数。
所以我的问题是:我什么时候需要在外部声明param,if 语句中的访问和构造函数调用有什么区别?我测试的两个编译器中的哪一个在这里做“正确”的事情,哪一个扩展了标准?
玩了一会儿,我意识到当我将 -O2 标志指定给 g++ 时它也可以工作。
【问题讨论】: