Edit: No, this is not right. See @Kornel's answer.
I'm not entirely sure but having consulted Stroustrup's "The C++ programming language" I think that Appendix C section 13.8.4 might be the cause.
Since frob
is a template one could conceivably specialise it for i=0
at a point after you call it. This means that the implementation would be left with two possible ways of choosing which frob
to call as it appears it can choose it at the point of instantiation or at the end of processing the translation unit.
So, I think the problem is you could do
namespace ns {
struct foo {};
template<int i> void frob(foo const&) {}
}
int main() {
ns::foo f;
frob<0>(f);
return 0;
}
namespace ns {
template<> void frob< 0 >(foo const&) { /* Do something different*/ }
}