Consider these cases:
int i{};
int& ir{i};
class A{
public:
int& i;
A(int&& pi):i(pi){}
};
A a1{i}; // Error // case 1
A a2{int(1)}; // OK // case 2
class B{
public:
int& i;
template<typename TYPE>
B(TYPE&& pi):i(pi){}
};
B b1{i}; // OK // case 3
B b2{int(1)}; //OK // case 4
int& ii{int(12)}; // Error // case 5
int& iii{std::move(int(12))}; // Error // case 6
template<typename TYPE>
class C{
public:
TYPE& i;
C(TYPE&& pi):i(pi){}
};
C c1{i}; // Error // case 7
C c2{int(1)}; // OK // case 8
C<int&> c3{i}; // OK // case 9
C<int&> c4{int(1)}; // Error // case 10
int&& iiii{ir}; // Error // case 11
A rvalue can not be bound to lvalue and if my understanding is correct, TYPE&&
would either collapse to TYPE&&
or TYPE&
.
How ever I am having a hard time understanding these cases, specially case 4. If case 4 is correct, then it means we have b2.i
which is a reference, initialized from a temporary (rvalue). Then why case 2, 5, 6 and 7 are incorrect? And when case 9 is correct it mean the TYPE&&
is int&&&
which (I assume) collapses to int&
, then how could c3.i
which is an rvalue(int&&
) be initialized from a lvalue, while case 10 and 11 are incorrect?
I wish some one could explain the general rules regarding this subject and also these cases in detail.