条款三 了解decltype

基础知识

提供一个变量或者表达式,decltype会返回其类型,但是返回的内容会使人感到奇怪。

以下是一些简单的推断类型:

const int i = ; // decltype(i) -> const int
bool f(const Widget& w); // decltype(w) -> const Widget&, decltype(f) -> bool(const Widget&)
struct Point {
int x, y;
} // decltype(Point::x) -> int
Widget w; // decltype(w) -> Widget
if(f(w)); // decltype(f(w)) -> bool
template<typename T>
class vector {
public:
T& operator[](std::size_t index);
};
vector<int> v; // decltype(v) -> vector<int>
if(v[] == ); // decltype(v[0]) -> int&

在C++11中,decltype的主要作用是推断根据形参类型推断返回类型。

对于std::vector<bool>,operator[]返回的并不是bool&,而是一个新的对象。

一种返回类型的推断的用法:

template<typename Container, typename Index>
auto authAndAccess(Container& c, Index i) -> decltype(C[i]){
authenticateUser();
return c[i];
}

C++11允许允许单语句lambda返回类型的推断,C+14扩展到所有lambda和函数。

// C++14版本,但是会有问题
template<typename Container, typename Index>
auto authAndAccess(Container& c, Index i){
authenticateUser();
return c[i];
}

以上函数虽然使用了auto,但套用auto的规则会出问题。如以上c[i]返回int&,但是根据推断规则会去掉引用类型,造成不能修改。

以下代码可以正确返回类型:

// C++14版本,可以正确返回类型
template<typename Container, typename Index>
decltype(auto) authAndAccess(Container& c, Index i){
authenticateUser();
return c[i];
}

auto与decltype(auto)的区别:

Widget w;
const Widget& cw = w;
auto myWidget1 = cw; // myWidget1 -> Widget
decltype(auto) myWidget2 = cw; // myWidget2 -> const Widget&

为了使得函数可以同时传入左值和右值,函数引入通用引用,正确形式如下:

// final C++14 version
template<typename Container, typename Index>
decltype(auto) authAndAccess(Container&& c, Index i){
authenticateUser();
return std::forward<Container>(c)[i];
} // final C++1 version
template<typename Container, typename Index>
auto authAndAccess(Container&& c, Index i)
-> decltype(std::forward<Container>(c)[i]){
authenticateUser();
return std::forward<Container>(c)[i];
}

在使用decltype时,变量外加上括号会改变推断类型:

int x = ;
decltype(x); // -> int
decltype((x)); // -> int&

总结

  • decltype总是产生没经过修改的变量或表达式的类型
  • 对于类型为T的左值表达式而非变量名,decltype总是返回T&类型
  • C++14支持decltype(auto),其就像auto一样从初始化中推断类型,但是使用decltype的来推断类型

[Effective Modern C++] Item 3. Understand decltype - 了解decltype的更多相关文章

  1. [Effective Modern C++] Item 2. Understand auto type deduction - 了解auto类型推断

    条款二 了解auto类型推断 基础知识 除了一处例外,auto的类型推断与template一样.存在一个直接的从template类型推断到auto类型推断的映射 三类情况下的推断如下所示: // ca ...

  2. [Effective Modern C++] Item 1. Understand template type deduction - 了解模板类型推断

    条款一 了解模板类型推断 基本情况 首先定义函数模板和函数调用的形式如下,在编译期间,编译器推断T和ParamType的类型,两者基本不相同,因为ParamType常常包含const.引用等修饰符 t ...

  3. [Effective Modern C++] Item 7. Distinguish between () and {} when creating objects - 辨别使用()与{}创建对象的差别

    条款7 辨别使用()与{}创建对象的差别 基础知识 目前已知有如下的初始化方式: ); ; }; }; // the same as above 在以“=”初始化的过程中没有调用赋值运算,如下例所示: ...

  4. [Effective Modern C++] Item 6. Use the explicitly typed initializer idiom when auto deduces undesired types - 当推断意外类型时使用显式的类型初始化语句

    条款6 当推断意外类型时使用显式的类型初始化语句 基础知识 当使用std::vector<bool>的时候,类型推断会出现问题: std::vector<bool> featu ...

  5. [Effective Modern C++] Item 5. Prefer auto to explicit type declarations - 相对显式类型声明,更倾向使用auto

    条款5 相对显式类型声明,更倾向使用auto 基础知识 auto能大大方便变量的定义,可以表示仅由编译器知道的类型. template<typename It> void dwim(It ...

  6. [Effective Modern C++] Item 4. Know how to view deduced types - 知道如何看待推断出的类型

    条款四 知道如何看待推断出的类型 基础知识 有三种方式可以知道类型推断的结果: IDE编辑器 编译器诊断 运行时输出 使用typeid()以及std::type_info::name可以获取变量的类型 ...

  7. Effective Modern C++ Item 27:重载universal references

    假设有一个接收universal references的模板函数foo,定义如下: template<typename T> void foo(T&& t) { cout ...

  8. Effective Modern C++ Item 37:确保std::thread在销毁时是unjoinable的

    下面这段代码,如果调用func,按照C++的标准,程序会被终止(std::terminate) void func() { std::thread t([] { std::chrono::micros ...

  9. Effective Modern C++ 42 Specific Ways to Improve Your Use of C++11 and C++14

    Item 1: Understand template type deduction. Item 2: Understand auto type deduction. Item 3: Understa ...

随机推荐

  1. iOS 之 cocoapods安装与使用

    我们都知道第三方库,一般使用cocoapods管理,cocoapods在我们IOS开发中有着很大的作用. 好了,现在看下它的安装步骤: 1.打开终端,输入 sudo gem install cocoa ...

  2. TRIGGERS_监测系统_原始数据表触发器—调用告警信息存储过程

    //每次向originaldata表中插入数据就会触发该触发器 create or replace trigger originaldata_to_alarm  after insert on ori ...

  3. 在函数中处理html点击事件在标签中增加属性值来解决问题。

  4. 50个必备的实用jQuery代码段+ 可以直接拿来用的15个jQuery代码片段

    50个必备的实用jQuery代码段+ 可以直接拿来用的15个jQuery代码片段 本文会给你们展示50个jquery代码片段,这些代码能够给你的javascript项目提供帮助.其中的一些代码段是从j ...

  5. text-overflow 文字溢出时的设置

    text-overflow : clip | ellipsis clip: 不显示省略标记(...),而是简单的裁切. ellipsis: 当对象内文本溢出时显示省略标记(...) 设置或检索是否使用 ...

  6. MyEclipse6.5安装SVN插件的三种方法

    MyEclipse6.5安装SVN插件的三种方法 方法一.如果可以上网可在线安装 1. 打开Myeclipse,在菜单栏中选择Help→Software Updates→Find and Instal ...

  7. Effective Java2读书笔记-创建和销毁对象(二)

    第3条:用私有构造器或者枚举类型强化Singleton属性 这一条,总体来说,就是讲了一个小技巧,将构造器声明为private,可以实现单例.具体有以下几种实现的方式. ①最传统的单例实现模式,可能有 ...

  8. 正则取页面图片URL和TABLE BackGround

    /// <summary> /// 根据html文本返回url地址集合 /// </summary> /// <param name="sHtmlText&qu ...

  9. SVN的错误: working copy locked

    提示:your working copy appears to be locked. run cleanup to amend the situation. 产生这种情况大多是因为上次svn命令执行失 ...

  10. cf479C Exams

    C. Exams time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...