static_cast to Universal Reference

90 Views Asked by At

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

  1. What are the differences of static_cast<T> and static_cast<T&&> if they are used in template?
  2. 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.

0

There are 0 best solutions below