1. 理解模板类型推导

1. expr是T&

template<typename T>
void f(T & param);
// 我们声明如下变量
int x = 27;
const int cx = x;
const int& rx = x;

函数调用时,推导出的Param和T的类型如下:

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的引用性被忽略了。

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 类型对象推导通常和模板类型推导是相同的。

例子:

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 一般情况下总是返回变量名或者表达式的类型而不做任何的修改。

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&
// 注:可以在模板中使用

特例:

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

modern effective C++ -- Deducint Types的更多相关文章

  1. Item 15: 只要有可能,就使用constexpr

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 如果说C++11中有什么新东西能拿"最佳困惑奖" ...

  2. Item 21: 比起直接使用new优先使用std::make_unique和std::make_shared

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 让我们先从std::make_unique和std::make_s ...

  3. Item 20: 使用std::weak_ptr替换会造成指针悬挂的类std::shared_ptr指针

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 矛盾的是,我们很容易就能创造出一个和std::shared_ptr ...

  4. Item 19: 使用srd::shared_ptr来管理共享所有权的资源

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 使用带垃圾回收机制语言的程序员指出并嘲笑C++程序员需要遭受防止资 ...

  5. Item 18: 使用srd::unique_ptr来管理独占所有权的资源

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 当你需要一个智能指针的时候,std::unique_ptr通常是最 ...

  6. Item 17: 理解特殊成员函数的生成规则

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 C++的官方说法中,特殊成员函数是C++愿意去主动生成的.C++9 ...

  7. Item 16: 让const成员函数做到线程安全

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 如果我们在数学领域里工作,我们可能会发现用一个类来表示多项式会很方 ...

  8. Item 14: 如果函数不会抛出异常就把它们声明为noexcept

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 在C++98中,异常规范(exception specificat ...

  9. Item 13: 比起iterator优先使用const_iterator

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 STL中的const_iterator等价于pointers-to ...

随机推荐

  1. YOLO2 (3) 快速训练自己的目标

    1快速训练自己的目标 在 YOLO2 (2) 测试自己的数据 中记录了完整的训练自己数据的过程. 训练时目标只有一类 car. 如果已经执行过第一次训练,改过一次配置文件,之后仍然训练同样的目标还是只 ...

  2. WIN10 + VS 2013 配置Opencv2.4.1.3 32位

    VS2013 配置Opencv2.4.1.3    32位 系统变量 Path: F:\2biancheng_tool\Opencv2413\opencv\build\x86\vc12\bin 用户变 ...

  3. day10,11-Python 基本数据类型介绍之数字与字符串(看看就好)

    数字:int #字符串转换整型 a = "123" print(type(a),a) b = int(a) print(type(b),b) b = b + 1000 print( ...

  4. leetcode 958. Check Completeness of a Binary Tree 判断是否是完全二叉树 、222. Count Complete Tree Nodes

    完全二叉树的定义:若设二叉树的深度为h,除第 h 层外,其它各层 (1-h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树. 解题思路:将树按照层进行遍历,如果 ...

  5. 深入浅出的webpack构建工具--webpack4+vue+router项目架构(十四)

    阅读目录 一:vue-router是什么? 二:vue-router的实现原理 三:vue-router使用及代码配置 四:理解vue设置路由导航的两种方法. 五:理解动态路由和命名视图 六:理解嵌套 ...

  6. 静态分析Android程序

    快速定位Android程序的关键代码 1.通过apktool反编译apk文件,得到AndroidManifest.xml文件,可以得到程序用到的组建.配置.以及主Activity 2.信息反馈法(特殊 ...

  7. 2018AVA: A Video Dataset of Spatio-temporally Localized Atomic Visual Actions

    论文标题:AVA: A Video Dataset of Spatio-temporally Localized Atomic Visual Actions 来源/作者机构情况: 谷歌,http:// ...

  8. linux内存源码分析 - SLAB分配器概述

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 之前说了管理区页框分配器,这里我们简称为页框分配器,在页框分配器中主要是管理物理内存,将物理内存的页框分配给申请 ...

  9. xml中的四则运算与时间爱格式

    取值第一个 和最后一个<tr> <td height="28" colspan="2" style="font-size:14px& ...

  10. QueryHelper

    [1].[代码] QueryHelper.java 跳至 [1] package my.db; import java.io.Serializable; import java.math.BigInt ...