TheRiver | blog

You have reached the world's edge, none but devils play past here

0%

move forward

参考

cppreference

move

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /// remove_reference
template<typename _Tp>
struct remove_reference
{ typedef _Tp type; };

template<typename _Tp>
struct remove_reference<_Tp&>
{ typedef _Tp type; };

template<typename _Tp>
struct remove_reference<_Tp&&>
{ typedef _Tp type; };

//std::move
template<typename _Tp>
constexpr typename std::remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }

std::move只保证转换成右值,并不保证一定可以移动。如下,const导致的问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <type_traits>

using namespace std;

class bb{
public:
bb() = default;
bb(const bb&){
cout << "copy construct" << endl;
}

bb(bb &&){
cout << "move construct" << endl;
}
};

template<class T1, class T2>
void print_is_same() {
std::cout << std::is_same<T1, T2>() << '\n';
}

int main()
{
const bb p1;
bb p2 = std::move(p1); //copy construct
print_is_same<const bb &, decltype(std::move(p1))>(); //0
print_is_same<bb &&, decltype(std::move(p1))>(); //0
print_is_same<const bb &&, decltype(std::move(p1))>(); //1

const int b = 10;
const int & a = std::move(b); //const左值引用可以赋值为const的右值

return 0;
}

forward

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* @brief Forward an lvalue.
* @return The parameter cast to the specified type.
*
* This function is used to implement "perfect forwarding".
*/
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type& __t) noexcept
{ return static_cast<_Tp&&>(__t); }

/**
* @brief Forward an rvalue.
* @return The parameter cast to the specified type.
*
* This function is used to implement "perfect forwarding".
*/
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
{
static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
" substituting _Tp is an lvalue reference type");
return static_cast<_Tp&&>(__t);
}

完美转发推导

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>

int makeint()
{
return int();
}

template <typename T>
void func(T&& param){
//test(std::forward<T>(param));
}

//按书上的说法,右值引用经由通用引用后的T是int,这样推导的话forward没有用到第二种实现
//网上有的地方说T是int&&,第二种forward的实现就用到了,做个问题留下来以后再说吧
int main()
{
//rvalue
func(makeint());
#if 0
//makeint()返回右值: int &&
//T推导成int
//完美转发
template<typename int>
constexpr int&&
forward(typename std::remove_reference<int>::type& __t) noexcept
{ return static_cast<int&&>(__t); }
//转换
constexpr int&&
forward(typename int& __t) noexcept
{ return int&&(__t); }
#endif

//lvalue
int a;
func(a);
#if 0
//a是左值
//T推导成int &
//完美转发
template<typename int&>
constexpr int&&&
forward(typename std::remove_reference<int&>::type& __t) noexcept
{ return static_cast<int&&&>(__t); }
//转换
constexpr int&
forward(typename int& __t) noexcept
{ return int&(__t); }
#endif

}

引用折叠

引用折叠针对的是引用(a)的引用(b),a/b有一个是左值则结果是左值,反之是右值

引用折叠出现的场景

  • 模板实例化(通用引用)
  • auto型别生成
  • 创建和运用typedef
  • decltype

ending

2020071501.jpg

----------- ending -----------