I have been playing around with template classes and constants in gcc 4.8.2 and came across an interesting linker error:
#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;
}
Compiling the code in the current state gives a linker error, telling me that A::param
is not defined.
Trying this code in Visual Studio 2008 as well, it compiles and links without any problems. On gcc, it compiles when I either use the external declaration of the param
constant, or if I replace a.param
with 0 or nothing on the line indicated.
What I do not understand is why the line containing the if
statement can use a.param
without compilation error, while I cannot pass a.param
to the constructor without declaring it externally.
So my question is: When do I need to declare param
externally, and what is the difference between the access in the if
statement and the constructor call? Which of the two compilers I tested does the "right" thing here, and which one has extended the standard?
Playing around a little more, I realized it also works when I specify the -O2 flag to g++.