I'm trying to get my head around perfect forwarding in C++, and so I've written the following quick and dirty bit of code to test this.
class CValue
{
public:
    CValue(int i) :
        m_i(i)
    {
        printf("Default constructor called!\r\n");
    }
    CValue(const CValue& src) :
        m_i(src.m_i)
    {
        printf("Copy constructor called!\r\n");
    }
    CValue(CValue&& src) :
        m_i(src.m_i)
    {
        printf("Move constructor called!\r\n");
    }
    CValue& operator=(const CValue& src)
    {
        m_i = src.m_i;
        printf("Copy assignment called!\r\n");
        return *this;
    }
    CValue& operator=(CValue&& src)
    {
        m_i = src.m_i;
        printf("Move assignment called!\r\n");
        return *this;
    }
    int     m_i;
};
template <typename T>
void PerfectForwarding(T&& tValue)
{
    T tValue1 = tValue;
    tValue1.m_i = 10;
}
int _tmain(int argc, _TCHAR* argv[])
{
    CValue v(0);
    PerfectForwarding(v);
    printf("%d\r\n", v.m_i);
    return 0;
}
When I build and run this code as a console application I get the answer 10, when I was expecting 0.
It seems that the line:
T tValue1 = tValue;
in the PerfectForwarding function is being resolved to:
CValue& tValue1 = tValue;
instead of:
CValue tValue1 = tValue;
So the compiler is resolving T to be CValue&, which I didn't expect.
I tried invoking the function from _tmain by explicitly declaring the template parameter type, i.e.
PerfectForwarding<CValue>(v);
but this fails to compile with the following error:
error C2664: 'void PerfectForwarding<CValue>(T &&)' : cannot convert
              argument 1 from 'CValue' to 'CValue &&'
              with
              [
                  T=CValue
              ]
You cannot bind an lvalue to an rvalue reference
I can force the desired behaviour through changing the line in the PerfectForwarding function to the following:
typename std::remove_reference<T>::type tValue1 = tValue;
but I didn't think this should be necessary. By the reference collapsing rules the type of the argument (T&&) should become CValue& (as T&& & -> T&), but T itself should be simply CValue, surely? Is this a bug in the VC12 compiler's handling of rvalue references, or am I misunderstanding something about rvalue references and templates?
I'm using Visual Studio 2013 (VC12 compiler) in debug with all optimisation turned off.
 
     
     
     
    