//Start here
foo f; // default-initialize `f`, call the default constructor
relay(std::move(f));
std::move(f)
does the same asstatic_cast<foo&&>(f)
, so it actually doesn't "do" anything; it merely produces an rvalue expression ("f
is treated as an rvalue").relay( std::move(f) )
instantiatesvoid relay<foo>(foo&& arg)
and calls this function. The parameter is a reference and reference-compatible with the argument, hence no constructor is called.
mfoo(std::forward<T>(arg))
std::forward<T>(arg)
yieldsarg
as an lvalue ifT
is an lvalue reference, or as an rvalue ifT
is not an lvalue reference. I.e., forT == foo&&
, it does the same asstd::move(arg)
. No constructor is called.mfoo(..)
finally callsmfoo
, which takes its argument by value. This causes a copy or move, depending on the type and the value category of the argument expression.
As our argument expression here is an rvalue, the move constructor will be called (if existent and accessible).