06 当auto推导出非预期类型时应当使用显式的类型初始化

06 当auto推导出非预期类型时应当使用显式的类型初始化

1. auto推导出非预期类型

​ 有时候 auto 的类型推导会和你想的南辕北辙。举一个例子,假设我有一个函数接受一个 Widget 返回一个 std::vector<bool> ,其中每个 bool 表征 Widget 是否接受一个特定的特性:

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

​ 假设要取第5个bool

Widget w;
// ...
bool highPriority = features(w)[5];
// ...
processWidget(w, highPriority);

​ 这份代码没有任何问题。它工作正常。但是如果我们做一个看起来无伤大雅的修改,把 highPriority 的显式的类型换成 auto

auto highPriority = features(w)[5];

processWidget(w, highPriority); // 未定义行为

​ 正如注释中所提到的,调用 processWidget 现在会导致未定义的行为。但是为什么呢?答案是:在使用 auto 的代码中,highPriority 的类型已经不是 bool 了。

​ 尽管 std::vector<bool> 从概念上说是 bool 的容器,对 std::vector<bool>operator[] 运算符并不一定是返回容器中的元素的引用( std::vector::operator[] 对所有的类型都返回引用,就是除了 bool )。

​ 事实上,他返回的是一个 std::vector<bool>::reference 对象(一个在 std::vector<bool> 中内嵌的class)。

2. 显式的类型初始化原则

​ 不管你是如何发现它们,一旦 auto 被决定作为推导代理类的类型而不是它被代理的类型,它就不需要涉及到关于 autoauto 自己本身没有问题。问题在于 auto 推导的类型不是所想让它推导出来的类型。

​ 解决方案就是强制一个不同的类型推导。 我把这种方法叫做显式的类型初始化原则。 显式的类型初始化原则涉及到使用 auto 声明一个变量,但是转换初始化表达式到 auto 想要 的类型。下面就是一个强制 highPriority 类型是 bool 的例子:

auto highPriority = static_cast<bool>(features(w)[5]);