[Effective Modern C++] Item 3. Understand decltype - 了解decltype

了解decltype

基础知识

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

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

const int i = 0; // 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[0] == 0); // 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 = 0;
decltype(x); // -> int
decltype((x)); // -> int&

总结

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

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

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

条款一 了解模板类型推断 基本情况 首先定义函数模板和函数调用的形式如下,在编译期间,编译器推断T和ParamType的类型,两者基本不相同,因为ParamType常常包含const.引用等修饰符 template<typename T> void f(ParamType param); // 函数模板形式 f(expr); // 函数调用 存在T的类型即为expr类型的情况,如下T为int templat<typename T> void f(const T& param

《Effective Modern C++》翻译--条款3: 理解decltype

条款3:理解decltype decltype 是一个非常有趣的怪兽.如果提供了一个名字或是表达式,decltype关键字将会告诉你这个名字或这个表达式的类型.通常情况下,结果与你的期望吻合.然而有些时候,decltype产生的结果领你挠头,使你去翻阅参考书或在网上问答中寻求答案. 我们先从通常的情况开始-这里没有暗藏惊喜.联系到在模板类型推导和auto类型推导中发生了什么,decltype关键字就像鹦鹉学舌一样,对于变量名称或表达式类型的推导跟模板类型推导和auto类型推导没有任何变化: co

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

条款6 当推断意外类型时使用显式的类型初始化语句 基础知识 当使用std::vector<bool>的时候,类型推断会出现问题: std::vector<bool> features(const Widget& w); // OK bool highPriority = features(w)[5]; processWidget(w, highPriority); // ERROR auto highPriority = features(w)[5]; processWid

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

条款7 辨别使用()与{}创建对象的差别 基础知识 目前已知有如下的初始化方式: int x(0); int y = 0; int z{0}; int z = {0}; // the same as above 在以“=”初始化的过程中没有调用赋值运算,如下例所示: Widget w1; // default ctor Widget w2 = w1; // copy ctor w1 = w2; // assignment, operator = 还可以用来初始化: class Widget {

Effective Modern C++ 读书笔记 Item 1

最近发现了<Effective Modern C++>这本书,作者正是大名鼎鼎的Scott Meyers——<Effective C++>.<Effective STL>的作者. 而就在C++11逐渐普及,甚至是C++14的新特性也进入大家的视野的时候,<Effective Modern C++>一书应运而生.此书与其前辈一样,通过数十个条款来展开,只不过这次是集中于C++11和C++14的新特性.auto.decltype.move.lambda表达式……

《Effective Modern C++》Item 1总结

Item 1: Understand template type deduction. 理解模板类型推导 template<typename T> void f(ParamType param); The type deduced for T is dependent not just on the type of expr, but also on the form of ParamType. 对于T类型推导,不仅依赖传入模板表达式也依赖ParamType的形式. ParamType is

《Effective Modern C++》读书笔记 Item 2 auto的类型推导

注意: 还要学习一个 ↑↑↑↑ 这样的方框里的片段完全不来自于原书,而是我自己的理解. Item 2 Understand auto type deduction - auto类型推导 在C++11之前,auto 关键字一直是用于声明自动储存类型的变量时使用的,基本上没有什么实际作用,地位和 export 关键字(用于向编译单元之外导出模板,也在C++11中被取消)类似. 在C++11中,auto 终于不再废材,终于具备了类似C#中 var 关键字的效果,可以自动推导出变量的类型,可以少打几个字

Effective Modern C++

1. Deducing Types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Item 1: Understand template type deduction. Item 2: Understand auto type deduction. Item 3: Understand decltype

《Effective Modern C++》要点中英文对照

目录 CHAPTER 1 Deducing Types 章节1 类型推导 Item 1:Understand template type deduction. 条款1:理解模板类型推导. Item 2:Understand auto type deduction. 条款2:理解auto类型推导. Item 3:Understand decltype. 条款3:理解decltype. Item 4:Know how to view deduced types. 条款4:知道如何查看推导出来的类型.