[
Example 3: 
Here is an example in which different parameter/argument pairs produce
inconsistent template argument deductions:
template<class T> void f(T x, T y) {  }
struct A {  };
struct B : A {  };
void g(A a, B b) {
  f(a,b);           
  f(b,a);           
  f(a,a);           
  f(b,b);           
}
Here is an example where two template arguments are deduced from a
single function parameter/argument pair
.This can lead to conflicts
that cause type deduction to fail:
template <class T, class U> void f(T (*)(T, U, U));
int g1(int, float, float);
char g2(int, float, float);
int g3(int, char, float);
void r() {
  f(g1);            
  f(g2);            
  f(g3);            
}
Here is an example where the exception specification of a function type
is deduced:
template<bool E> void f1(void (*)() noexcept(E));
template<bool> struct A { };
template<bool B> void f2(void (*)(A<B>) noexcept(B));
void g1();
void g2() noexcept;
void g3(A<true>);
void h() {
  f1(g1);           
  f1(g2);           
  f2(g3);           
}
Here is an example where a qualification conversion applies between the
argument type on the function call and the deduced template argument type:
template<class T> void f(const T*) { }
int* p;
void s() {
  f(p);             
}
Here is an example where the template argument is used to instantiate
a derived class type of the corresponding function parameter type:
template <class T> struct B { };
template <class T> struct D : public B<T> {};
struct D2 : public B<int> {};
template <class T> void f(B<T>&) {}
void t() {
  D<int> d;
  D2     d2;
  f(d);             
  f(d2);            
}
 — end example]