So I was just writing a sample and contrived example of std::forward for my understanding, but it didn't work the way I expected. In the program below
#include <string>
#include <iostream>
struct A
{
    A(const std::string& m) : m_(m) {};
    std::string m_;
};
template<typename T>
void funcB(T&& obj)  // universal reference
{
    std::string local = std::move(obj.m_);   // using std::move on universal reference. Bad.
    std::cout << "funcB : " << local << '\n';
}
template<typename T>
void funcC(T&& obj)  // universal reference
{
    std::string local = std::forward<std::string>(obj.m_);   // using std::move on universal reference
    std::cout << "funcC : " << local << '\n';
}
template<typename T>
void funcD(T&& obj)  // universal reference
{
    T local = std::forward<T>(obj);   // using std::move on universal reference
    std::cout << "funcD : " << local.m_ << '\n';
}
int main()
{
    A obj("firstString");
   //funcA(obj);  // We get compiler error. Rvalue reference cannot be bound to Lvalue
    funcB(obj);  
    std::cout << "Main : " <<  obj.m_ << '\n';
    A obj2("secondString");
    funcC(obj2);
    std::cout << "Main : " << obj2.m_ << '\n';
    A obj3("thirdString");
    funcD(obj3);
    std::cout << "Main : " << obj3.m_ << '\n';
}
In the output
funcB : firstString
Main : 
funcC : secondString
Main : 
funcD : thirdString
Main : thirdString
In funcC, even though I have used universal references and here it is bound to Lvalue, the string is moved when I do std::forward<std::string>. Hence the in the last line, after "Main:" there is no output. Can someone please how the string is moved even though obj is bound to Lvalue.
Just realized the answer to this, after rereading a book.
In funcC, std::forward<std::string>(obj.m_) is equivalent to moving the string.
But in funcD, std::forward is instantiated as std::forward<struct A&>(obj), which is copied. 
 
    