编辑我错过了一个重要的细节,地图是const
。该示例已更新。
考虑
const std::map<int, int> ints;
auto& it = ints.find(0);
回顾C ++(工作草案)规范以及Stroustrup的“The C ++ Programming Language,FOURTH EDITION”,我无法确定是否需要const
(我确实认为{{1}明确地修改了类型在风格上更好,但这不是我的问题)。 Visual Studio 2013编译得很好,推导出const
。
我知道裸const
(即auto
和const
之类的装饰品)不会推断出非常规的非参照类型。
在Stroupstrup的书中的每个例子中,他使用&
而不是const auto&
来表示这种情况。 编辑但他没有说明使用auto&
的选项/需要,他们只是const
的例子。
gcc 4.9.1无法编译它,xcode for mac也是如此:
auto
这些编译器选择吗?规范是否说明了这一点?
感谢。
答案 0 :(得分:1)
是的,这种行为完全是标准规定的:
[C++11: 7.1.6.4/5]:
在本节未明确允许的上下文中使用auto
的程序格式不正确。
[C++11: 7.1.6.4/6]:
根据8.3确定 declarator-id 的类型后,确定使用 declarator-id 的声明变量的类型从其初始化程序的类型使用模板参数推导的规则。设T
为已为变量标识符d确定的类型。通过使用新发明的类型模板参数P
替换auto的出现次数,或者如果初始化程序是 braced-init-list ,则从T
获取U
(8.5.4),std::initializer_list<U>
。 从变量d
推导出的类型是使用函数调用(14.8.2.1)中的模板参数推导规则确定的推导A
,其中P
是函数模板参数类型和d
的初始化程序是相应的参数。如果扣除失败,则声明格式不正确。
[C++11: 14.8.2.1/3]:
如果P
是cv限定类型,则P
类型的顶级cv限定符将被忽略以进行类型推导。如果P
是引用类型,P
引用的类型将用于类型推导。如果P
是对cv-nonqualified模板参数的右值引用,则参数是左值,类型“A
的左值参考”用于代替A
进行类型扣除。
您已经添加了&
(即使std::map<int, int>::find const
要返回引用也是必需的,顺便说一句,这不是必需的);现在添加const
(按上述要求)!
答案 1 :(得分:0)
您的错误原因是尝试将临时对象绑定到非const的左值引用。
考虑这个例子:
int i = 42;
const int ci = 42;
auto& a = i; // type of i is int, value category of i is lvalue -- OK
auto& b = ci; // type of ci is const int, value category of ci is lvalue -- OK
auto& c = 42; // type of 42 is int, value category of 42 is rvalue -- error
auto
会根据模板广告扣除规则推断出初始化表达式的类型,因此a
为int&
,b为const int&
。
但是如果初始化表达式是非const rvalue,如文字42
或ints.find(0)
,auto
将推导出非const类型,那么c
是int&
(对非const的左值引用),它不会绑定到右值。
auto&& d = i; // d is int& -- OK
auto&& e = ci; // e is const int& -- OK
auto&& f = 42; // f is int&& -- OK
auto&&
是一个转发引用,它将推导出初始化表达式的cv-qualification(constness)和value类别。