std::forward完美转发


#include <iostream>
#include <boost/type_index.hpp>

template<typename _Tp>
  constexpr _Tp&&
  forward(typename std::remove_reference<_Tp>::type& __t) noexcept  // 实参为左值时
  {
      std::cout <<"forward(&):std::is_same<int, _Tp>():" << std::is_same<int, _Tp>() << std::endl;
      std::cout <<"forward(&):std::is_same<int&, _Tp>():" << std::is_same<int&, _Tp>() << std::endl;
      std::cout <<"forward(&):std::is_same<int&&, _Tp>():" << std::is_same<int&&, _Tp>() << std::endl;
      std::cout << "run _Tp&" << std::endl;
      return static_cast<_Tp&&>(__t);
  }

template<typename _Tp>
  constexpr _Tp&&
  forward(typename std::remove_reference<_Tp>::type&& __t) noexcept // 实参为右值时
  {
      std::cout <<"forward(&&):std::is_same<int, _Tp>():" << std::is_same<int, _Tp>() << std::endl;
      std::cout <<"forward(&&):std::is_same<int&&, _Tp>():" << std::is_same<int&&, _Tp>() << std::endl;
      std::cout << "run _Tp&&" << std::endl;
      // 因为实参为右值,所以模板推断指定类型_Tp不能为左值引用类型,
      // 因为如果是左值引用 static_cast<_Tp &&>类型转换就会是static_cast<& &&>就会变成一个左值引用,一个右值变成一个左值引用显然是不对的
      static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
    " substituting _Tp is an lvalue reference type");
      return static_cast<_Tp&&>(__t);
  }

template<typename T>
void Tprint(T&& t)
{
    std::cout << "Tprint:std::is_same<int &, T>():" << std::is_same<int &, T>() << std::endl;
}

template<typename T>
void foo(T&& fparam)
{
    forward<T>(fparam);
}

int main()
{
    int a = 100;
    const int b = 101;
    int& lref = a;
    int&& rref = std::move(a);

    std::cout << "int a: type is " << boost::typeindex::type_id_with_cvr<decltype(a)>().pretty_name() << std::endl;
    std::cout << "const int b: type is " << boost::typeindex::type_id_with_cvr<decltype(b)>().pretty_name() << std::endl;
    std::cout << "int& lref: type is " << boost::typeindex::type_id_with_cvr<decltype(lref)>().pretty_name() << std::endl;
    std::cout << "int&& rref: type is " << boost::typeindex::type_id_with_cvr<decltype(rref)>().pretty_name() << std::endl;

    Tprint(rref);
    forward<int>(1);
    std::cout << "forward<int>(lref): type is " << boost::typeindex::type_id_with_cvr<decltype(forward<int>(lref))>().pretty_name() << std::endl;//这个将左值转化成了右值
    std::cout << "forward<int &>(lref): type is " << boost::typeindex::type_id_with_cvr<decltype(forward<int &>(lref))>().pretty_name() << std::endl;

    foo(1);
   
    return 0;
}
//编译:g++ prog.cc -Wall -Wextra -I/opt/wandbox/boost-1.83.0-gcc-13.2.0/include -std=c++11
运行结果:
prog.cc: In instantiation of 'void Tprint(T&&) [with T = int&]':
prog.cc:51:11:   required from here
prog.cc:28:17: warning: unused parameter 't' [-Wunused-parameter]
   28 | void Tprint(T&& t)
      |             ~~~~^
int a: type is int
const int b: type is int const
int& lref: type is int&
int&& rref: type is int&&
Tprint:std::is_same(int &, T):1
forward(&&):std::is_same<int, _Tp>():1
forward(&&):std::is_same<int&&, _Tp>():0
run _Tp&&
forward(lref): type is int&&
forward(lref): type is int&
forward(&):std::is_same<int, _Tp>():1
forward(&):std::is_same<int&, _Tp>():0
forward(&):std::is_same<int&&, _Tp>():0
run _Tp&
C++11中std::move和std::forward到底干了啥(最后一个例子t为右值引用类型是个左值所以调用的是forward的左值版本不是右值版本,写的完全错了 浅谈std::move和std::forward原理 https://wandbox.org/permlink/tUy8bm3XKLkoTBiF
 
喜欢 0
分享