std::forward()
In this note, we simulate part of std's type_trait to understand the magic part of C++.
std::is_lvalue_reference && std::is_rvalue_reference
template <typename T>
struct jr_is_lvalue_reference       : public std::false_type { }
template <typename T>
struct jr_is_lvalue_reference<T&>   : public std::true_type { }
template <typename T>
struct jr_is_rvalue_reference       : public std::false_type { }
template <typename T>
struct jr_is_rvalue_reference<T&&>  : public std::true_type { }
Usage
template <typename T>
void foo(){
    cout<<std::jr_is_lvalue_reference<T>::value<<endl;
    cout<<std::jr_is_rvalue_reference<T>::value<<endl;
    cout<<endl;
}
int main(int argc, const char* argv[]){
    std::vector<int> v;
    std::vector<int>& ref = v;
    
    // call foo with explicit instantiation
    foo<decltype(ref)>();
    foo<decltype(std::move(v))>();
}
The output is
1
0
0
1
Let's try to understand is, first, is the reference collapsing rule of C++.
class X { };
X& &&, X&& &, X& &  -->  X&
X&& &&              -->  X&&
When we call
foo<decltype(ref)>();
/*  
 * T of foo() is std::vector<int>&, 
 *  std::jr_is_lvalue_reference<T>  =>  std::jr_is_lvalue_reference<std::vector<int>&>
 *  it calls the partial instantiation:
 *
 *      template <typename T>
 *      struct jr_is_lvalue_reference<T&> : public true_type{ }
 *
 *  here T is std::vector<int>
 *
 */
 
 foo<decltype(std::move(v))>();
/* 
 * Almost same,
 * Here just call foo() with rvalue reference instantiation
 */
std::remove_reference
template <typename T>
struct jr_remove_reference     { typedef type T; }
template <typename T>
struct jr_remove_reference<T&> { typedef type T; }
template <typename T>
struct jr_remove_reference<T&&>{ typedef type T; }
Just a struct and 2 partial instantiations.
std::forward()
And now let's simulate .
template <typename T>
T&& jr_forward(typename jr_remove_reference<T>::type& t){
    return static_cast<T&&>(t);
}
templat <typename T>
T&& jr_forwad(typename jr_remove_reference<T>::type&& t){
    static_assert(!jr_is_lvalue_reference<T>::value, "cannot forward a rvalue as a lvalue");
    return static_cast<T&&>(t);
}
Since we try to forward a type to another type, we must say which type we want to forward to, it's obvious that we must call  or  with explicit instantiation.
Use and understand std::forward()
Let's try to understand this.
class X{ };
void g(X&){
    cout<<"f() for X&"<<endl;
}
void g(X&&){
    cout<<"f() for X&&"<<endl;
}
void g(const X&){
    cout<<"f() for const X&"<<endl;
}
int main(int argc, const char* argv[]){
    X v;
    const X c;
    
    g(v);
    g(c);
    g(X{});
    g(std::move(v));
}
Output is
g() for X& 
g() for const X& 
g() for X&& 
g() for X&& 
If we want to unify all variations of  in a , we may write something like this.
template <typename T>
void f(T& val){
    g(std::forward<T>(val));
}
And in 
int main(){
    X v;
    const X c;
    
    f(v);
    f(c);
}
The output is
g() for X&& 
g() for const X& 
Is there some thing wrong.
For , which should be called is, it called  is called, but it did the right thing in .
Sure, when you call ,   for  is ,actually, we called  and  returns .
but in ,  won't be droped during function calling, so, let suppose
using type = const X&.
We're actually calling  in .  of  is , and  returns , according to the collapsing rule,  becomes .
Beside this, there're more errors.
if we do this in 
int main(){
    X v;
    const X c;
    
    f(X());
    f(std::move(v));
}
It won't even compile, the error is 
Sure,  takes a lvalue reference as parameter, how can we pass a rvalue reference to it !!!
Perfect forwarding
And to uniform all s, we can write something like this, it's the trikey use of rvalue reference.
template <typename T>
void f(T&& val){
    g(std::forward<T>(val));
}
int main(int argc, const char* argv[]){
    X v;
    const X c;
    
    f(v);
    f(c);
    f(X{});
    f(std::move(v));
}
The output is
g() for X& 
g() for const X& 
g() for X&& 
g() for X&& 
It works well.
And, why?
First, when we call. We actually called , the  for  is ,  returns , a rvalue reference to a lvalue reference, it collapsed as  according the C++ reference collapsing rule, so  actually returns , it's straight forward that it calls .
And when we call . We actually called . And you're encouraged to do the rest deduction by yourself.
And last, when we call  for , we call  with a rvalue reference, we just called , the  for  is just .
Summarize
Let'e review the perfect forwarding.
template <typename T>
void f(T&& val){
    g(std::forward<T>(val));
}
To summarize, what we're actually is that,  always return a rvalue reference, when we pass a rvalue, we get a straight-forward rvalue, when we pass a lvalue, according to C++ reference collapsing rule, we get a lvalue.