Reputation: 53
from this code:
// Example program
#include <iostream>
#include <string>
struct Z { static const int z = 1; };
struct Y { static const int y = 2; };
template <typename A> struct TE { int foo(); int bar(); };
template <> int TE<Y>::bar() { return foo(); }
template <typename A> int TE<A>::bar() { return foo(); }
template <> int TE<Y>::foo() { return Y::y; }
template <typename A> int TE<A>::foo() { return A::z; }
template struct TE<Z>;
template struct TE<Y>;
int main()
{
TE<Z> z;
TE<Y> y;
std::cout << z.bar() << std::endl;
std::cout << y.bar() << std::endl;
return 0;
}
with this error
21:28: error: specialization of 'int TE<A>::foo() [with A = Y]' after instantiation
In instantiation of 'int TE<A>::foo() [with A = Y]':
13:12: required from here
28:15: error: 'z' is not a member of 'Y'
In member function 'int TE<A>::foo() [with A = Y]':
29:1: warning: control reaches end of non-void function [-Wreturn-type]
these implementations are done in separate cpp file. and the structs are in a header, typical explicit template instantiation.
why did this
int TE<Y>::bar() { return foo(); }
tries to use this
template <typename A> int TE<A>::foo() { return A::z; }
instead of this
template <> int TE<Y>::foo() { return Y::y; }
Upvotes: 1
Views: 716
Reputation: 66371
The problem is that your foo
specialization isn't known at the time bar
is instantiated, so foo
in both bar
s refers to the foo
base template.
As the first error message says, when the compiler gets to your Y
specialization, the base template has already been instantiated, using A = Y
.
The second error is a "cascade error" due to the specialization failure, in the grand C++ tradition.
If you rearrange the definitions, it works:
template <typename A> int TE<A>::foo() { return A::z; }
template <> int TE<Y>::foo() { return Y::y; }
template <typename A> int TE<A>::bar() { return foo(); }
template <> int TE<Y>::bar() { return foo(); }
Upvotes: 1
Reputation: 712
http://en.cppreference.com/w/cpp/language/template_specialization
Explicit specialization can only appear in the same namespace as the primary template, and has to appear after the non-specialized template declaration.
Also, you need to follow the One-Definition-Rule (ODR). So usually you would provide your implementations along in the same header.
Upvotes: 2