Effective C++: 模板类型推断.

特别需要注意的一点是:

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;
}

 

转载于:https://my.oschina.net/SHIHUAMarryMe/blog/649844

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值