modern effective C++ -- Deducint Types

1. 理解模板類型推導

1. expr是T&

template<typename T>
void f(T & param);
// 咱們聲明以下變量
int x = 27;
const int cx = x;
const int& rx = x;

函數調用時,推導出的Param和T的類型以下:ios

f(x);  // T is int, param's type is int&
f(cx); // T is const int, param's type is const int&
f(rx); // T is const int, param's type is const int&

須要特別註明的是,經過T&的方式傳入數組,數組的大小信息不會丟失。數組

template<typename T>
void f(T& param);
int arr[10];
f(arr); // T is const int[10], param type is const int(&)[10]

在類型推導期間,數組和函數將退化爲指針類型,除非他們是被初始化爲引用。函數

2. expr是const T&

template<typename T>
void f(const T& param);

int x = 27;
const int cx = x;
const int& rx = x;

在進行類型推導的時候,rx的引用性被忽略了。spa

f(x);  // T is int, param's type is const int&
f(cx); // T is int, param's type is const int&
f(rx); // T is int, param's type is const int&

3. param是一個指針類型

template<typename T>
void f(T* param); // param is now a pointer

int x = 27;
const int* px = &x;
f(&x); // T is int, param's type is int *
f(px); // T is const int, param's type is const int *

4. param是universial reference

template<typename T>
void f(T&& param); // param is now a universal reference

int x = 27;
const int cx = x;
const int rx = x;

f(x);  // x is lvalue, so T is int&, param's type is also int&
f(cx); // cx is lvalue, so T is const int&, param's type is also const int&
f(rx); // rx is lvalue, so T is const int&, param's type is also const int&
f(27); // 27 is rvalue, so T is int, param's typs is int&&

5. param 既不是指針也不是引用

template<typename T>
void f(T param);

當ParamType既不是指針也不是引用的時候,咱們按照值傳遞的方式進行處理。
須要舉出一個有用的例子:指針

template<typename T>
void f(T param);
const char* const ptr = "hello world\n";
f(ptr); // param's type is const char*

2. 理解auto自動類型推導

auto 類型對象推導一般和模板類型推導是相同的。
例子:code

const char name[] = "zhouyang";
auto arr1 = name; // arr1's type is const char*
auto& arr2 = name; // arr2's type is const char(&)[9]
void someFunc(int, double); // someFunc is a function
auto func1 = someFunc; // func1's type is void(*)(int, double)
auto& func2 = someFunc; // func2's type is void(&)(int, double)

惟一的例外是:使用auto和大括號進行初始化時,自動推導爲std::initializer_list。而且,對於使用括號進行的初始化,模板類型推導會失敗。對象

3. 理解decltype

decltype 通常狀況下老是返回變量名或者表達式的類型而不作任何的修改。get

const int i = 0; // decltype(i) is const int
bool f(const Widget& w) // decltype(w) is const Widget&
Widget W; // decltype(w) is Widget

在C++14中,提供了decltype(auto)的支持,它從初始化式子中推導類型,使用的是decltype的推導規則。編譯器

Widget w;
cosnt Widget& cw = w;
auto myWidget1 = cw; // myWidget1's type is Widget
decltype(auto) myWidget2 = cw; // decltype type deduction:
                               // myWidget2's type is const Widget&
// 注:能夠在模板中使用

特例:it

#include <iostream>
using namespace std;

int main()
{
  int temp = 10;

  decltype((temp)) temp1 = temp; // temp1's type is int& 
  temp1 = 1;
  cout<< temp << endl;
  
  return 0;
}
//輸出 : 1

4. 瞭解如何查看推導出的類型

能夠利用編譯器診斷來完成。咱們想要知道被推導出的類型,能夠首先聲明一個類模板,可是不定義它。那麼編譯器的出錯信息會包含推導的類型信息。

template<typename T>
class TD;

經過編譯器內置的宏定義,能夠輸出函數類型

#include <iostream>
#include <vector>

using namespace std;

void test_func(int)
{
#if defined(__GNUC__)
  cout << __PRETTY_FUNCTION__ << endl;
#elif defined(_MSC_VER)
  cout << __FUNCSIG__ << endl;
#endif
}

int main()
{
  test_func(10);

  return 0;
}
相關文章
相關標籤/搜索