如果能看懂以下示例,标题中的相关术语应该都能理解:
定义函数模板:
//E.h文件
#pragma once
#include<iostream>
//万能引用而非右值引用
template<typename T>
void print(T&&n)
{
std::cout << n << std::endl;
}
template<typename T>
void print(T&n)
{
std::cout << n << std::endl;
}
//函数模板涉及类型T推导,T&&是万能引用而非右值引用
//当n为左值时传递给T&&时,T会被推导为左值引用,
//此时触发引用折叠,T&& &->T&,此时实参与形参类别同为左值引用,因此可以传递左值引用--primerP609
template<typename T>
void printfun(T&&n)
{
//n为左值,如果不进行完美转发总是会调用void print(T&n)
//print(n);
//完美转发,根据n情况选择调用函数
print(std::forward<T>(n));
}
类模板
template<typename T>
class F
{
public:
//类模板无需类型推导,T&&是右值引用
void printfun(T&&n)
{
//虽然传进来的是右值,即允许右值实参绑定到形参右值引用,但形参右值引用是一个变量,变量即为左值
//因此n为左值,总会调用void print(T&n)左值函数
print(n);
//转换右值调用void print(T&&n)右值函数
print(std::move(n));
}
//
void print(T&&n)
{
std::cout <<"void F:: print(T&&n)"<< n << std::endl;
}
void print(T&n)
{
std::cout << "void F:: print(T&n)" << n << std::endl;
}
};
main函数
#include <iostream>
#include"E.h"
#include"F.h"
int main()
{
int fs = 9;
printfun(std::move(fs));
printfun(fs);//形参是外能引用:实参可以为左值或右值
F<int>f;
f.printfun(std::move(fs));//形参是右值引用:实参必须为右值
f.print(5);
//f.printfun(fs);//编译错误
std::cout << "Hello World!\n";
}