《Effective Modern C++》Item 3总结

decltype 总结

第一个值得说明的问题是,operator[] on a container of objects of type T typically returns a T&.[]操作符用于储存T类型对象的容器时通常返回T&,具体问题需要具体分析,decltype一个[]操作符,返回类型依赖存储它的容器。vector<bool>就比较特殊。

template<typename Container, typename Index> // works, but
auto authAndAccess(Container& c, Index i) // requires
-> decltype(c[i]) // refinement
{
authenticateUser();
return c[i];
}

这段C++11代码有效,但是存在一下问题,我们使用位置返回类型,并且使用c和i,对于其他函数如果无法获取c和i,那么无法使用decltype。这个方法可以完善。

template<typename Container, typename Index> // C++14;
auto authAndAccess(Container& c, Index i) // not quite
{ // correct
 authenticateUser();
 return c[i]; // return type deduced from c[i]
}

这段C++14代码不正确,从条款一,二可知,auto会把左值引用识别为去掉引用的部分,这里其实我们需要返回左值引用。

template<typename Container, typename Index> // C++14; works,
decltype(auto) // but still
authAndAccess(Container& c, Index i) // requires
{ // refinement
authenticateUser();
return c[i];
}

decltype(auto)终于搞定了,我们不在需要尾置返回类型,并且类型识别为左值引用。但是这个方法仍然需要完善。

因为我们仍然需要面临一个问题,这个模板无法使用右值。所以无法传入一个临时的容器对象。我们需要支持类似下面的操作

std::deque<std::string> makeStringDeque(); // factory function
// make copy of 5th element of deque returned
// from makeStringDeque
auto s = authAndAccess(makeStringDeque(), 5);

那么需要引入新词语,全球通引用和完美转发,今年C++标准委员会开大会,决定把universal references正式更名为forwarding references(转发引用),转发引用一般用与完美转发,需要深入了解一下std::forward和std::move两个函数,以及右值引用和左值引用区别,这个后续条款有讲,并且我也打算专门为右值引用写一片文章。

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

这样一切都搞定了。

最后需要注意一些小问题,比如

int x;

decltype((x)) //type is int&

更详细的细节:

1) If the argument is either the unparenthesised name of an object/function,sion (object.member or pointer-> or is a member access expresmember), then the decltype specifies the declared type of the entity specified by this expression.

2) If the argument is any other expression of type T, then

a) if the value category of expression is xvalue, then the decltype specifies T&&

b) if the value category of expression is lvalue, then the decltype specifies T&

c) otherwise, decltype specifies T

除了括号非常特殊以外,decltype((变量,只有名字的表达式))的类型总会是个引用。如果是一个简单的表达式(只有名字这种objec.member也算简单),那么decltype就是返回它的类型。

对于其他任何比较复杂的表达式,遵循2),

这里给出一个英文的连接,供参考什么是左值,右值,x值

http://en.cppreference.com/w/cpp/language/value_category

时间: 2024-10-27 10:57:14

《Effective Modern C++》Item 3总结的相关文章

[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 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++] 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 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

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表达式……

[C++11] Effective Modern C++ 读书笔记

本文记录了我读Effective Modern C++时自己的一些理解和心得. item1:模板类型推导 1)reference属性不能通过传值参数传入模板函数.这就意味着如果模板函数需要一个reference类型的参数,必须在模板声明中将其声明为reference,否则,即使使用一个reference类型的变量调用模板函数,类型推导的结果将不带reference属性. 2)constant和volatile属性也不能通过传值参数传入模板函数,但是可以通过reference参数传入这些属性. 3

决定干点事儿--翻译一下《effective modern c++》

写了很多关于C++11的博客,总是觉得不踏实,很多东西都是东拼西凑.市场上也很少有C++11的优秀书籍,但幸运的是Meyers老爷子并没有闲赋,为我们带来了<effective modern c++>. 我们都要认清,一个人很难超越自我,超越自我的巅峰之作.因为不同的时代,也会早就不同的伟大作品. 说上面这段话的意思就是,我们不能期待<effective modern c++>能达到<effective c++>给我们带来的惊喜,但是也是出自大师之手. Learn ho

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++》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 关键字的效果,可以自动推导出变量的类型,可以少打几个字