I don't understand where is m_i binded to.
m_i
is bound to the argument of A
's constructor. What is the argument of A
's constructor here?
In this case, since factory
does not forward its argument to A
(i.e. it does not use std::forward<>()
), then what is being passed to A
is an lvalue. This is because a1
is named, and named objects are lvalues.
The type of a1
is not relevant to determine whether a1
is an lvalue or an rvalue. So even though a1
has type rvalue-reference to int
(int&&
), as is the case in your program, the parameter a1
is itself a named object, and therefore it is an lvalue.
This means, since m_i
has type lvalue-reference to int
, that m_i
can be bound (and indeed is bound) to factory
's (lvalue) parameter a1
, which will be destroyed when factory()
returns. In other words, you're left with a dangling reference.
Attempting to dereference it (as you do later on in your program) summons Undefined Behavior.
However, if your factory()
function had forwarded its arguments to A
's constructor:
template<class T, class A1, class A2>
T* factory(A1&& a1, A2&& a2)
{
return new T(std::forward<A1>(a1), std::forward<A2>(a2));
}
This would have caused a compiler error, because the machinery of std::forward<>()
would make sure that lvalues stay lvalues, and rvalues stay rvalues. Attempting to bind an lvalue-reference to an rvalue is illegal, and therefore the call to A
's constructor would have failed.