Item 6: auto推导出非预期类型时请显示指定类型

Item 5 展示了一些使用auto定义变量的优势,但是auto在有些时候也会推导出一些我们不期望的类型。比如,一个函数通过传入一个Widget返回一个std::vector<bool>的类型,容器内的每一个bool值表示Widget的一个特征:

std::vector<bool> features(const Widget& w);

比如第5个bool值表示Widget是否是高优先属性,代码可以写成下面的形式:

Widget w;
...
bool highPriority = features(w)[5]; // w 是否是高优先属性?
...
processWidget(w, highPriority) // 根据是否是高优先性来处理 w
阅读更多 »Item 6: auto推导出非预期类型时请显示指定类型

5 点亮屏幕1(ssd1306)

视频教程:https://www.bilibili.com/video/BV1cA411E76c/

既然给女神做礼物,那么高逼格道具自然不能少,下面就是我们要用到的道具,ssd1306,0.96寸oled,分辨率128×64

图1 ssd1306

整个模块的尺寸大概是 NodeMCU 的一半,当然也有其他的尺寸。模块上有4个引脚,分别是GND(接地),VDD(也叫VCC,供电),SCK(也叫SCL,时钟信号),SDA(数据)。真正和ESP8266通讯的其实只有SCK和SDA,这就是I2C协议。

阅读更多 »5 点亮屏幕1(ssd1306)

Item 5: 推荐用 auto 定义类型

先观察下面两个例子:

int x;

是不是忘记了给 x 赋初值,因此现在它的值是不确定的。可能应该初始化成 0 吧。还是应该取决上下文吧。Get 到问题了吗?

我们再给局部变量的用迭代器解引用来进行初始化。

template <typename It>
void dwim(It b, It e)  //dwim 的算法是迭代 b 至 e 中所有的元素
{
  for (; b != e; ++b)
  {
    typename std::iterator_traits<It>::value_type currValue = *b;
    ...
  }
}

如果想知道迭代器值的类型,你要使用 “typename std::iterator_traits<It>::value_type” 来得到迭代器中值的类型,这非常考验你的记忆能力。

阅读更多 »Item 5: 推荐用 auto 定义类型

第二章 auto

从概念上看,auto 非常简单,其实它的细节有许多微妙之处。使用 auto 不但可以少敲键盘,而且可以防止手残而导致的错误或者低效的定义。此外,auto 定义的类型完全符合类型定义的规则。但是从程序员的角度来看的话,是错误的,因为程序员需要知道这里应该是什么类型,当然,退回到手动定义类型也是一种代替方法,但最好避免。

这个简短的介绍涵盖了 auto 的方方面面。

阅读更多 »第二章 auto

Item 4:查看推导类型

选择用什么工具查看类型推导结果取决于在什么开发阶段,需要获取什么样的信息。这里将探索三种阶段:编码阶段,编译阶段和运行阶段。

通过 IDE 编辑器运行信息

在使用 IDE 编码的过程中,当你把光标放在一些程序元素附近呢(比如,变量,参数,函数等等,IDE 时常会显示出程序元素的信息,例如,看下面的代码:

const int theAnswer = 42;

auto x = theAnswer;
auto y = &theAnswer;

IDE 会提示出类似 x 的推导类型是 int,b 的推导类型是 const int*。

阅读更多 »Item 4:查看推导类型

Item 3:理解 decltype

decltype 是一个奇怪的东西,给他传入一个变量名称或者表达式,它就能返回给i类型。通常情况下,它都能返回你想要知道的类型。然而,他的结果有时候会让你抓狂,到处找资料甚至在论坛上问别人。

不过说到这里,先不要害怕,我们首先从那些非常直观的 case 说起。与模版和 auto 相反,decltype 是通过你给出的名称或者表达式返回给你具体的类型:

const int i = 0;                      // decltype(i) 是 const int

bool f(const Widget& w);              // decltype(w) 是 const Widget&

struct Point {
  int x, y;                           // decltype(Point::x) 是 int
};                                    // decltype(Point::y) 是 int

Widget w;                             // decltype(w) 是 Widget

if (f(w)) ...                         // decltype(f(w)) 是 bool

template <typename T>                 // 这里是 std::vector 的简化版
class vector {
  ...
  T& operator[](std::size_t index);
  ...
};

vector<int> v;                        // decltype(v) 是 vector<int>
...
if (v[0] == 0) ...                    // decltype(v[0]) 是 int

看到了吗?非常直观,没有惊喜!

阅读更多 »Item 3:理解 decltype

Item 2:理解 auto 的推导

阅读完 Item 1 关于模板的推导,你基本上已经学会了推导 auto 所需要的知识,因为 auto 只有一个例外,这个在后面会讲到。模版类型推导包含了模版,函数以及函数的参数, 但 auto 并不处理以上任何一种情况,模版推导和 auto 之间的知识点为什么是一样的呢?

是的,就是这样。这里可以映射一套规则将模版推导和 auto 推导联系起来。从字面上来看,这好像是一个数学变换公式,将一个规则变换成另一个。

在 Item 1,用的是函数模版和函数调用来解释模版的推导:

template <typename T>
void f(ParamType param);      // 使用函数模版来推导

f(expr);                      // 使用函数调用来推导
阅读更多 »Item 2:理解 auto 的推导