Reputation: 7123
Given:
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
I get:
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
But why do I get the error?
S<T>::N
.This is with g++ 4.2.1 on Mac OS X 10.6.6.
Upvotes: 3
Views: 1336
Reputation: 361352
extern template class S<int>;
I think this line causes the error, as it tells the compiler to look for explicit instantiation of S<int>
somewhere, but no explicit instantiation exists. Hence the error.
Once you comment this line, I think the code should compile fine.
EDIT:
Well, see this : http://www.ideone.com/oQnOi
As I said, it compiles fine!
EDIT:
I think $9.4.2/4 (as quoted by Mark B) doesn't apply to the static members of class templates, as $14.5.1.3 [temp.static] doesn't mandate the static members to be defined at namespace scope:
A definition for a static data member may be provided in a namespace scope enclosing the definition of the static member’s class template.
The the example follows as,
template<class T> class X { static T s; };
template<class T> T X<T>::s = 0;
Notice, it doesn't say "must be provided", rather "may be provided". So I think the definition of static members of class template at namespace scope is optional.
Upvotes: 2
Reputation: 96241
From 9.4.2/2:
The declaration of a static data member in its class definition is not a definition and may be of an incomplete type other than cvqualified void. The definition for a static data member shall appear in a namespace scope enclosing the member’s class definition. In the definition at namespace scope, the name of the static data member shall be qualified by its class name using the :: operator.
And from 9.4.2/4:
If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constantinitializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions within its scope. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.
From these references we can infer ("...shall still be defined..." in 9.4.2/4) that if it's not defined then the program isn't well-formed.
Upvotes: 2