特别需要注意的一点是:
int a = 0;
int&& x=0;
int& y = a
const int z = 0;
const int& g=0;
上面的表达式都是左值!
但是如果是: (a+x) 得到的值就是右值, 或者std::move(a)
在此之前我们首先了解一下引用折叠:
有2种情况会产生引用折叠:
1, 当我们定义一个模板(无论是函数还是其他的什么)为 Type&& 的形式的时候.
2, 间接的创建引用的引用,
demo for 1:
template<typename T>
Node{ Node(T&&); Node(const T&)};
我们实例化的时候写成 Node<int&>那么Node的构造函数被实例化为: Node(int&)和Node(const int&).
demo for 2:
template<typename T>
using type = typename std::add_lvalue_reference<T>::type&;
引用折叠的规则:
&+& = &;
&+&&=&;
&&+&=&;
&&+&&=&&;
针对普通变量的情况:
case 1: T arg
#include <iostream>
template<typename T>
void print(T arg)
{
std::cout << std::boolalpha
<< std::is_same<T, int>::value << std::endl;
}
int main()
{
int x = 10;
int&& y = 20;
const int z = 30;
const int& p = 40;
print(x); //T的类型均为int.
print(y);
print(z);
print(p);
print(std::move(x));
print(50);
return 0;
}
case 2: const T arg
#include <iostream>
template<typename T>
void print(const T arg)
{
std::cout << std::boolalpha
<< std::is_same<T, int>::value << std::endl;
}
int main()
{
int x = 10;
int&& y = 20;
const int z = 30;
const int& p = 40;
print(x); //T的类型均为int.
print(y);
print(z);
print(p);
print(std::move(x));
print(50);
return 0;
}
case 3: T& arg
#include <iostream>
template<typename T>
void print(T& arg)
{
std::cout << std::boolalpha
<< std::is_same<T, int>::value
<< " "
<< std::is_same<T, const int>::value << std::endl;
}
int main()
{
int x = 10;
int&& y = 20;
const int z = 30;
const int& p = 40;
print(x); //T: int
print(y); //T: int (注意这里y其实是一个右值引用的左值.)
print(z); //T: const int
print(p); //T: const int
//print(std::move(x)); //error: 不能用一个左值绑定到一个右值.
//print(50); //error: 不能从一个 临时值 到左值.
return 0;
}
case 4: const T& arg
#include <iostream>
template<typename T>
void print(const T& arg)
{
std::cout << std::boolalpha
<< std::is_same<T, int>::value
<< " "
<< std::is_same<T, const int>::value
<< " "
<< std::is_same<T, int& >::value << std::endl;
}
int main()
{
int x = 10;
int&& y = 20;
const int z = 30;
const int& p = 40;
print(x); //T: int
print(y); //T: int (注意这里y其实是一个右值引用的左值.)
print(z); //T: int
print(p); //T: int
print(std::move(x)); // T: int
print(50);//T: int
return 0;
}
case 5: T&& arg
#include <iostream>
template<typename T>
void print(T&& arg)
{
std::cout << std::boolalpha
<< std::is_same<T, int>::value
<< " "
<< std::is_same<T, int&>::value
<< std::endl;
}
int main()
{
int x = 10;
int&& y = 20;
const int z = 20;
const int& a = 40;
print(x); //T: int& //引用折叠.
print(y); //T: int& //引用折叠.
print(z); //T: const int& //引用折叠.
print(a); //T: const int& //引用折叠.
print(std::move(x)); //T: int
print(50); //T: int
return 0;
}
针对数组的情况:
1,如果声明模板类型的时候 无论是: const T&, 还是const T的形式当传递一个指针(而不是数组)进来的时候声明中的const都会变成一个顶层const!
2, "shihuawoaini"这样的字符串的类型为 const char(&)[13]! (重点)
case 1: T arg
#include <iostream>
#include <type_traits>
template<typename T>
void print(T arg)
{
std::cout << std::boolalpha
<< std::is_same<T, char*>::value << " "
<< std::is_same<T, const char*>::value << " "
<< std::is_same<const char*, decltype(arg)>::value << " "
<< std::is_same<char* const, decltype(arg)>::value << " "
<< std::is_same<const char* const, decltype(arg)>::value << " "
<< std::endl;
}
template<typename T>
void printf(T arg)
{
std::cout << std::boolalpha
<< std::is_same<char*, decltype(arg)>::value << std::endl;
}
int main()
{
char strOne[] = "shihuawoaini";
char* strTwo = "shihuawaoaini";
const char* strThree = "shihuawoaini";
char* const strFour = "shihuawoaini";
const char* const strFive = "shihuawoaini";
char* strSix = new char[13]{ 's', 'h', 'i', 'h', 'u', 'a', 'w', 'o', 'a', 'i', 'n', 'i', '\0' };
char strSeven[13] = { 's', 'h', 'i', 'h', 'u', 'a', 'w', 'o', 'a', 'i', 'n', 'i', '\0' };
print(strOne); //T: char* arg的类型为: char*
print(strTwo); //T: char* arg的类型为: char*
print(strThree); //T: const char* arg的类型为: const char*
print(strFour); //T: char* arg的类型为: char*
print(strFive); //T: const char* arg的类型为: const char* (也就是说指针的顶层const被祛除掉了).
print(strSix); //T: char* arg的类型为: char*
print(strSeven); //T: char* arg的类型为: char*
print("shihuawoaini"); //T: const char* arg的类型为: const char*
printf(strFour); //arg的类型为: char* (也就是说指针的顶层const被祛除掉了).
delete[] strSix;
}
case 2: const T arg
#include <iostream>
#include <type_traits>
template<typename T>
void print(const T arg)
{
std::cout << std::boolalpha
<< std::is_same<T, char*>::value
<< " "
<< std::is_same<T, const char*>::value
<< " "
<< std::is_same<char* const, decltype(arg)>::value
<< " "
<< std::is_same<const char* const, decltype(arg)>::value
<< " "
<< std::is_same<const char* const, T>::value
<< std::endl;
}
int main()
{
char strOne[] = "shihuawoaini";
char* strTwo = "shihuawaoaini";
const char* strThree = "shihuawoaini";
char* const strFour = "shihuawoaini";
const char* const strFive = "shihuawoaini";
char* strSix = new char[13]{ 's', 'h', 'i', 'h', 'u', 'a', 'w', 'o', 'a', 'i', 'n', 'i', '\0' };
char strSeven[13] = { 's', 'h', 'i', 'h', 'u', 'a', 'w', 'o', 'a', 'i', 'n', 'i', '\0' };
//print(strOne); //T: char*, arg的类型为: char* const
//print(strTwo); //T: char* arg的类型为: char* const
//print(strThree); //T: const char* arg的类型为: const char* const
//print(strFour); //T: char* arg的类型为: char* const
//print(strFive); //T: const char* arg的类型为: const char* const
//print(strSix); //T: char* arg的类型为: char* const
//print(strSeven); //T: char* arg的类型为: char* const
print("shihuawoaini"); //T: const char* arg的类型为: const char* const
delete[] strSix;
}
case 3: T& arg
#include <iostream>
#include <type_traits>
template<typename T>
void print(T& arg)
{
std::cout << std::boolalpha
<< std::is_same<char[13], T>::value << " "
<< std::is_same<char*, T>::value << " "
<< std::is_same<const char*, T>::value << " "
<< std::is_same<char * const, T>::value << " "
<< std::is_same<const char* const, T>::value << " "
<< std::is_same<const char[13], T>::value << " "
<< std::endl;
}
template<typename T>
void print_f(T& arg)
{
std::cout << std::boolalpha
<< std::is_same<char(&)[13], decltype(arg)>::value << " "
<< std::is_same<char* &, decltype(arg)>::value << " "
<< std::is_same<const char* &, decltype(arg)>::value << " "
<< std::is_same<char* const&, decltype(arg)>::value << " "
<< std::is_same<const char* const&, decltype(arg)>::value << " "
<< std::is_same<const char(&) [13], decltype(arg)>::value << " "
<< std::endl;
}
int main()
{
char strOne[] = "shihuawoaini";
char* strTwo = "shihuawaoaini";
const char* strThree = "shihuawoaini";
char* const strFour = "shihuawoaini";
const char* const strFive = "shihuawoaini";
char* strSix = new char[13]{ 's', 'h', 'i', 'h', 'u', 'a', 'w', 'o', 'a', 'i', 'n', 'i', '\0' };
char strSeven[13] = { 's', 'h', 'i', 'h', 'u', 'a', 'w', 'o', 'a', 'i', 'n', 'i', '\0' };
//print(strOne); //T: char[13]
//print(strTwo); //T: char*
//print(strThree); //T: const char*
//print(strFour); //T: char* const
//print(strFive); //T: const char* const
//print(strSix); //T: char*
//print(strSeven); //T: char[13]
print("shihuawoaini"); //const char[13]
//print_f(strOne); //arg的类型为: char (&)[13]
//print_f(strTwo); //arg的类型为: char* &
//print_f(strThree); //arg的类型为: const char* &
//print_f(strFour); //arg的类型为: char* const &
//print_f(strFive); //arg的类型为: const char* const &
//print_f(strSix); //arg的类型为: char* &
//print_f(strSeven); //arg的类型为: char (&)[13]
print_f("shihuawoaini"); //arg的类型为: const char(&)[13]
delete[] strSix;
}
case 4: const T& arg
#include <iostream>
#include <type_traits>
template<typename T>
void print(const T& arg)
{
std::cout << std::boolalpha << " "
<< std::is_same<char[13], T>::value << " "
<< std::is_same<char*, T>::value << " "
<< std::is_same<const char*, T>::value << " "
<< std::is_same<const char(&)[13], T>::value << " "
<< std::endl;
}
template<typename T>
void print_f(const T& arg)
{
std::cout << std::boolalpha
<< std::is_same<const char(&)[13], decltype(arg)>::value << " "
<< std::is_same<char* const&, decltype(arg)>::value << " "
<< std::is_same<const char* const&, decltype(arg)>::value << " "
<< std::endl;
}
int main()
{
char strOne[] = "shihuawoaini";
char* strTwo = "shihuawaoaini";
const char* strThree = "shihuawoaini";
char* const strFour = "shihuawoaini";
const char* const strFive = "shihuawoaini";
char* strSix = new char[13]{ 's', 'h', 'i', 'h', 'u', 'a', 'w', 'o', 'a', 'i', 'n', 'i', '\0' };
char strSeven[13] = { 's', 'h', 'i', 'h', 'u', 'a', 'w', 'o', 'a', 'i', 'n', 'i', '\0' };
//print(strOne); //T: char[13]
//print(strTwo); //T: char*
//print(strThree); //T: char*
//print(strFour); //T: const char*
//print(strFive); //T: char*
//print(strSix); //T: char*
//print(strSeven); //T: char[13]
print("shihuawoaini"); //T: char[13]
//print_f(strOne); //arg的类型为: const char (&)[13]
//print_f(strTwo); //arg的类型为: char* const&
//print_f(strThree); //arg的类型为: const char* const&
//print_f(strFour); //arg的类型为: char* const&
//print_f(strFive); //arg的类型为: const char* const&
//print_f(strSix); //arg的类型为: char* const&
//print_f(strSeven); //arg的类型为: const char (&)[13]
print_f("shihuawoaini"); //arg的类型为: const char(&)[13]
delete[] strSix;
}
case 4: T&& arg
#include <iostream>
#include <type_traits>
template<typename T>
void print(T&& arg)
{
std::cout << std::boolalpha << " "
<< std::is_same<char(&)[13], T>::value << " "
<< std::is_same<char* &, T>::value << " "
<< std::is_same<const char* &, T>::value << " "
<< std::is_same<const char* const&, T>::value << " "
<< std::is_same<char* const&, T>::value << " "
<< std::is_same<const char(&)[13], T>::value << " "
<< std::endl;
}
template<typename T>
void print_f(T&& arg)
{
std::cout << std::boolalpha
<< std::is_same<char(&)[13], decltype(arg)>::value << " "
<< std::is_same<char* &, decltype(arg)>::value << " "
<< std::is_same<char* const&, decltype(arg)>::value << " "
<< std::is_same<const char* const&, decltype(arg)>::value << " "
<< std::is_same<const char* &, decltype(arg)>::value << " "
<< std::is_same<const char(&)[13], decltype(arg)>::value << " "
<< std::endl;
}
int main()
{
char strOne[] = "shihuawoaini";
char* strTwo = "shihuawaoaini";
const char* strThree = "shihuawoaini";
char* const strFour = "shihuawoaini";
const char* const strFive = "shihuawoaini";
char* strSix = new char[13]{ 's', 'h', 'i', 'h', 'u', 'a', 'w', 'o', 'a', 'i', 'n', 'i', '\0' };
char strSeven[13] = { 's', 'h', 'i', 'h', 'u', 'a', 'w', 'o', 'a', 'i', 'n', 'i', '\0' };
//
//print(strOne); //T: char (&)[13]
//print(strTwo); //T: char* &
//print(strThree); //T: const char* &
//print(strFour); //T: char* const&
//print(strFive); //T: const char* const&
//print(strSix); //T: char* &
//print(strSeven); //T: char (&)[13]
print("shihuawoaini"); //const char(&) [13]
//print_f(strOne); //arg的类型为: char (&)[13]
//print_f(strTwo); //arg的类型为: char* &
//print_f(strThree); //arg的类型为: const char* &
//print_f(strFour); //arg的类型为: char* const&
//print_f(strFive); //arg的类型为: const char* const&
//print_f(strSix); //arg的类型为: char* &
//print_f(strSeven); //arg的类型为: char (&)[13]
print_f("shihuawoaini"); //arg的类型为: const char(&)[13]
delete[] strSix;
}
针对函数类型:
case 1: T arg
#include <iostream>
#include <type_traits>
void function(const int& value)
{
std::cout << value << std::endl;
}
void function_f(const int& value)noexcept
{
std::cout << value << std::endl;
}
template<typename T>
void print(T arg)
{
std::cout << std::boolalpha
<< std::is_same<void(const int&), T>::value << " "
<< std::is_same<void(const int&), T>::value << " "
<< std::is_same<void(*)(const int&), T>::value << " "
<< std::is_same<void(*)(const int&)noexcept, T>::value<< " "
<< std::endl;
}
template<typename T>
void print_f(T arg)
{
std::cout << std::boolalpha
<< std::is_same<void(const int&), decltype(arg)>::value << " "
<< std::is_same<void(const int&)noexcept, decltype(arg)>::value <<" "
<< std::is_same<void(*)(const int&), decltype(arg)>::value << " "
<< std::is_same<void(*)(const int&)noexcept, decltype(arg)>::value << " "
<< std::endl;
}
int main()
{
//true!!!!!!!!!!!!
std::cout << std::boolalpha << std::is_same<void(const int&), decltype(function)>::value << std::endl;
print(function); //T: void(*)(const int&)或者void(*)(const int&)noexcept
print(&function); //T: void(*)(const int&)或者void(*)(const int&)noexcept
print(function_f);//T: void(*)(const int&)或者void(*)(const int&)noexcept
print(&function_f);//T: void(*)(const int&)或者void(*)(const int&)noexcept
/*
print_f(function); //arg的类型为: void(*)(const int&)也可以是void(*)(const int&)noexcept
print_f(&function);//arg的类型为: void(*)(const int&)也可以是void(*)(const int&)noexcept
print_f(function_f);//arg的类型为: void(*)(const int&)也可以是void(*)(const int&)noexcept
print_f(&function_f);//arg的类型为: void(*)(const int&)也可以是void(*)(const int&)noexcept
*/
return 0;
}
case 2: T&& arg
#include <iostream>
#include <fstream>
#include <string>
void printValue(const int& val)
{
std::cout << val << std::endl;
}
void printVal(const int& val)noexcept
{
std::cout << val << std::endl;
}
template<typename Ty>
void functionAsPra(Ty&& func)
{
std::cout << std::boolalpha
<< std::is_same<void(&)(const int&), decltype(func)>::value << " "
<< std::is_same<void(&)(const int&)noexcept, decltype(func)>::value << " "
<< std::endl;
std::cout << "---------------------------------" << std::endl;
std::cout << std::is_same<void(*&&)(const int&), decltype(func)>::value << " "
<< std::is_same<void(*&&)(const int&)noexcept, decltype(func)>::value << " "
<< std::endl;
std::cout << "---------------------------------" << std::endl;
std::cout << std::is_same<void(*&)(const int&), decltype(func)>::value << " "
<< std::is_same<void(*&)(const int&), decltype(func)>::value << " "
<< std::endl;
std::cout << "----------------------------------" << std::endl;
std::cout << std::is_same<void(*&)(const int&), Ty>::value << " "
<< std::is_same<void(*&)(const int&), Ty>::value << " "
<< std::endl;
std::cout << "----------------------------------" << std::endl;
std::cout << std::is_same<void(*&&)(const int&), Ty>::value << " "
<< std::is_same<void(*&&)(const int&)noexcept, Ty>::value << " "
<< std::endl;
std::cout << "---------------------------------" << std::endl;
std::cout << std::is_same<void(*)(const int&), Ty>::value << " "
<< std::is_same<void(*)(const int&)noexcept, Ty>::value << " "
<< std::endl;
std::cout << "---------------------------------" << std::endl;
std::cout << std::is_same<void(&)(const int&), Ty>::value << " "
<< std::is_same<void(&)(const int&)noexcept, Ty>::value << " "
<< std::endl;
}
int main()
{
using Type = void(*)(const int&);
Type func = &printValue;
//case 1:
//functionAsPra(printValue);
//T的类型为: void(&)(const int&)/void(&)(const int&)noexcept;
//T&& func中func的类型为: void(&)(const int&)/void(&)(const int&)noexcept;
//case 2:
//functionAsPra(&printValue);
//T的类型为: void(*)(const int&)/void(*)(const int&)noexcept;
//T&& func中func的类型为: void(*&&)(const int&)/void(*&&)(const int&)noexcept;
//case 3:
functionAsPra(func);
//T的类型为: void(*&)(const int&)/void(*&)(const int&)noexcept;
//T&& func中func的类型为: void(*&)(const int&)/void(*&)(const int&)noexcept;
return 0;
}