// translation unit 1: template<class T> void f(T*); void g(int* p) { f(p); // calls f<int>(int*) }
// translation unit 2: template<class T> void f(T); void h(int* p) { f(p); // calls f<int*>(int*) }
template<class T> void f(); template<int I> void f(); // OK: overloads the first template // distinguishable with an explicit template argument list
template <int I, int J> A<I+J> f(A<I>, A<J>); // #1 template <int K, int L> A<K+L> f(A<K>, A<L>); // same as #1 template <int I, int J> A<I-J> f(A<I>, A<J>); // different from #1
template <int I, int J> void f(A<I+J>); // #1 template <int K, int L> void f(A<K+L>); // same as #1 template <class T> decltype(g(T())) h(); int g(int); template <class T> decltype(g(T())) h() // redeclaration of h() uses the earlier lookup { return g(T()); } // ...although the lookup here does find g(int) int i = h<int>(); // template argument substitution fails; g(int) // was not in scope at the first declaration of h()
// Guaranteed to be the same template <int I> void f(A<I>, A<I+10>); template <int I> void f(A<I>, A<I+10>); // Guaranteed to be different template <int I> void f(A<I>, A<I+10>); template <int I> void f(A<I>, A<I+11>); // Ill-formed, no diagnostic required template <int I> void f(A<I>, A<I+10>); template <int I> void f(A<I>, A<I+1+2+3+4>);