条款三 了解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. 面试题:Java静态/非静态方法重写

    1.非静态方法重写 public class Test { public static void main(String[] args) throws Exception { Tree pine = ...

  2. (原)使用intel的ipp库计算卷积及相关

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5462631.html 参考网址: https://software.intel.com/zh-cn/n ...

  3. (原)Opencv中直方图均衡和图像动态范围拉伸的代码

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5102032.html 参考网址: http://blog.csdn.net/abcjennifer/a ...

  4. hibernate update部分更新

    hibernate update Hibernate 中如果直接使用 Session.update(Object o); 会把这个表中的所有字段更新一遍. 比如: view plaincopy to ...

  5. mysql之主从复制

    原理--> 在数据库层面,复制语句或者行,因为在数据库层面,故只有主服务器生成,并放到二进制日志里面,才能复制给从服务器. 原理--> mysql的主从复制基于异步,主要有三个进程执行,分 ...

  6. HC-MAC: A Hardware-Constrained Cognitive MAC for Efficient Spectrum Management

    IEEE JOURNAL ON SELECTED AREAS IN COMMUNICATIONS, VOL. 26, NO. 1, JANUARY 2008 正如上篇文章提到的,这篇论文设计的Mac协 ...

  7. IIC的标准操作函数集(C51)包含C和H文件

    /********************************************************************* 头文件名 VIIC_C51.H 这个头文件对应的库是VII ...

  8. IIS缺少文件的解决方法

    原文 http://cqyccmh.blog.163.com/blog/static/6068134720102211543944/ 今天解决了一个郁闷了很久的问题,之前实在没辙就只能重装系统,因为装 ...

  9. DFS(深度优先搜索)模板

    void dfs()//参数用来表示状态 { if(到达终点状态) { ...//根据题意来添加 return; } if(越界或者是不符合法状态) return; for(扩展方式) { if(扩展 ...

  10. convertView

    [convertView] 参考:https://zhidao.baidu.com/question/423895201122905772.html