Compiling the following testcase: enum Flavor { A, B }; template<enum Flavor F> class C { protected: template<typename T> static T f(T x) { if (F == A) return x; else return ~x; } }; class AC : public C<A> { private: typedef C<A> super; public: using super::f; }; unsigned int explicit_variable(unsigned int x) { unsigned int (*func)(unsigned int) = AC::f<unsigned int>; return func(x); } unsigned int explicit_call_instantiation(unsigned int x) { return AC::f<unsigned int>(x); } unsigned int implicit_call_instantiation(unsigned int x) { return AC::f(x); } produces: template-instantiation-bug.cpp: In function ‘unsigned int explicit_variable(unsigned int)’: template-instantiation-bug.cpp:11:12: error: ‘static T C<F>::f(T) [with T = unsigned int, Flavor F = (Flavor)0u]’ is protected template-instantiation-bug.cpp:32:44: error: within this context template-instantiation-bug.cpp:11:12: error: ‘static T C<F>::f(T) [with T = unsigned int, Flavor F = (Flavor)0u]’ is protected template-instantiation-bug.cpp:32:44: error: within this context template-instantiation-bug.cpp:11:12: error: ‘static T C<F>::f(T) [with T = unsigned int, Flavor F = (Flavor)0u]’ is protected template-instantiation-bug.cpp:32:44: error: within this context It is not obvious to me that this is the right answer, given that both explicit_call_instantiation and implicit_call_instantiation work. All versions of GCC that I've tested reject the testcase (4.4 - 4.8). Clang (2.8 - 3.2) accepts the testcase. MSVC version 9 rejects it. My MSVC version 10 installation appears to be busted, or I'd test it there too.
GCC 4.8.0 trunk behaves similar. I think the situation is currently not clear by the language. It looks like a manifestation of http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1551 to me. Especially bullet 3 in the P/R looks relevant to me.
Reduced testcase: class C { protected: template<typename T> static T f(T x){return x;} }; struct AC : C { using C::f; }; unsigned int (*func)(unsigned int) = AC::f;