I'm new to modern c++, and got messed up with value categories. There is discusssion about 'forward<T> vs static_cast<T&&>' Which says the purpose of using forward is to write clean code.
My question is
- What are the differences of static_cast<T> and static_cast<T&&> if they are used in template?
- Probably this is extended question. Why the direct use of static_cast<T> works fine unlike static_cast<T> in customized _forward function?
#include <iostream>
using namespace std;
void printInt(int& i) { cout << "lvalue reference: " << i << endl; }
void printInt(int&& i) { cout << "rvalue reference: " << i << endl; }
/* std::forward
*
* template<class _Ty>
* _NODISCARD constexpr _Ty&& forward(remove_reference_t<_Ty>& _Arg) noexcept
* { // forward an lvalue as either an lvalue or an rvalue
* return (static_cast<_Ty&&>(_Arg));
* }
*
* template<class _Ty>
* _NODISCARD constexpr _Ty&& forward(remove_reference_t<_Ty>&& _Arg) noexcept
* { // forward an rvalue as an rvalue
* static_assert(!is_lvalue_reference_v<_Ty>, "bad forward call");
* return (static_cast<_Ty&&>(_Arg));
* }
*/
template<class T>
T&& _forward(typename remove_reference<T>::type& arg) {
return static_cast<T>(arg);
}
template<typename T>
void test(T&& x) {
printInt(x); // x itself is lvalue
printInt(std::move(x)); // convert x into rvalue
printInt(std::forward<T>(x)); // inference reference type
printInt(static_cast<T&&>(x));
printInt(_forward<T>(x));
printInt(static_cast<T>(x));
}
int main() {
int a = 5;
cout << "pass lvalue" << endl;
test(a);
cout << "pass rvalue" << endl;
test(10);
}
[output]
pass lvalue
lvalue reference: 5
rvalue reference: 5
lvalue reference: 5
lvalue reference: 5
lvalue reference: 5
lvalue reference: 5
pass rvalue
lvalue reference: 10
rvalue reference: 10
rvalue reference: 10
rvalue reference: 10
rvalue reference: 17823636
rvalue reference: 10
printInt(x); // x itself is lvalue
printInt(std::move(x)); // convert x into rvalue
printInt(std::forward<T>(x)); // inference reference type
printInt(static_cast<T&&>(x));
works as expected.
printInt(_forward<T>(x));
printInt(static_cast<T>(x));
However, why does static_cast<T>(x) works same with static_cast<T&&>(x)? It seems like it should print out rvalue only. And why the case using _forward prints dummy value?
I just guess, maybe, xvalue is relevant with these results. But cannot explain clearly.