1.6.3.1 template type
template<typename T> 
void f(ParamType param); 
 
f(expr); // deduce T and ParamType from expr

  1. ParamType is a Reference or Pointer, but not a Universal Reference. If expr’s type is a reference, ignore the reference part. Then pattern-match expr’s type against ParamType to determine T.
    template<typename T> 
    void f(T& param); // param is a reference 
     
    int x = 27; // x is an int 
    const int cx = x; // cx is a const int 
    const int& rx = x; // rx is a reference to x as a const int 
     
    f(x); // T is int, params type is int& 
    f(cx); // T is const int, params type is const int& 
    f(rx); // T is const int, params type is const int&
  2. ParamType is a Universal Reference

    1. If expr is an lvalue, both T and ParamType are deduced to be lvalue references. although ParamType is declared using the syntax for an rvalue reference, its deduced type is an lvalue reference.
    2. If expr is an rvalue, the "normal" (i.e., Case 1) rules apply.
    template<typename T> 
    void f(T&& param); // param is now a universal reference 
    int x = 27; // as before 
    const int cx = x; // as before 
    const int& rx = x; // as before 
     
    f(x); // x is lvalue, so T is int&, params type is also int& 
    f(cx); //cx is lvalue, so T  and params type are const int& 
    f(rx); //rx is lvalue, so T  and params type are const int& 
    f(27); //27 is rvalue, so T is int, params is therefore int&&
  3. ParamType is Neither a Pointer nor a Reference. As before, if expr’s type is a reference, ignore the reference part. If, after ignoring expr’s reference-ness, expr is const, ignore that, too. If it’s volatile, also ignore that.
    template<typename T> 
    void f(T param); // param is now passed by value 
     
    int x = 27; // as before 
    const int cx = x; // as before 
    const int& rx = x; // as before 
    f(x); // Ts and params types are both int 
    f(cx); // Ts and params types are again both int 
    f(rx); // Ts and params types are still both int
  4. Conclusion: Take four steps to decide:
    1. array or function decay to pointer, if they are not used to reference ParamType
    2. universal reference for lvaue, T is lvalue reference. (keep const)
    3. reference is ignored
    4. for value-type ParamType, const and volatile are ignored.