9_2_universal_reference.cpp
#include "hjcommon.hpp"
static void bcd(int &&num) {}
template<typename T>
static void cde(const T &&t) {} // 不是万能引用,const 会剥夺 T&& 的万能引用性质
template<typename T>
static void abc(T &&t) {} // 万能引用
template<typename T>
static void def(vector<T>&& vec) {} // 不是万能引用
template<typename T> class A
{
public:
void func1(T&& t) {} // 不是万能引用,是右值引用
template<typename W>
void func2(W&& w) {} // 万能引用
};
int main_2_9_2(int argc, char *argv[])
{
int num = 0;
// bcd(num); // 不可以,不可以将左值赋给右值引用
bcd(0); // 可以
// cde<int>(num); // 不可以
// cde(num); // 不可以
cde(0); // 可以
// abc<int>(num); // 不可以
abc(num); // 可以,但若是函数模板形参改为 const T && ,就又不行了
abc(0); // 可以
// universal reference 万能引用/未定义引用
// 万能引用语境:必须是函数模板、必须是发生了模板类型推断并且函数模板形参样子必须是 T&&, (const T&& 不行)、auto也存在万能引用的概念
// 此时 T&& 就称为万能引用,若传参左值,那么此时万能引用会变成左值引用。若传参右值,那么此时万能引用会变成右值
auto &&a1 = 0; // 可以,也是万能引用
auto &&a2 = num; // 可以,也是万能引用
A<int> a;
// a.func1(num); // 不可以
a.func2(num); // 可以
return 0;
}
9_4_引用折叠_完美转发_forward.cpp
#include "hjcommon.hpp"
template<typename F, typename T, typename Q>
static void tempPerfectFunc(F f, T&& t, Q&& q) // 使用万能引用,既能保持const属性,又能保持左值右值属性
{
// 通过函数模板去调用另一个普通函数,这种形式就叫转发。
f(std::forward<T>(t), std::forward<Q>(q)); // 在万能引用的基础上转发时使用 std::forward<>() 就能实现完美转发。
}
static int aFunc(int &a, int &&b)
{
++a;
return a+b;
}
int main_2_9_4(int argc, char *argv[])
{
// 引用折叠(引用坍塌),c++11 : 当编译器发生类型推断出现多个 & 时,就会发生引用折叠,左-左、左-右、右-左 这三种只要左值的情况,最终变量会折叠为左值, 右-右 折叠为右值。
// 引用的引用: int a=0; int &b=a; int & &c=b; // 语法明写会报错,但是编译器在进行类型推断时可能会出现这种引用的引用,这时会用引用折叠来处理。
// 转发、完美转发、std::forward(还原变量的左值或右值属性)
int a = 10;
tempPerfectFunc(aFunc, a, 50); // 完美转发
cout << "a=" << a << endl; // a=11
// std::forward<>() 另外用法
int b = 0;
int &&c = std::forward<int>(b); // 利用forward将左值转右值
return 0;
}