在他的 CppCon 2014 演讲中 "Type Deduction and Why You Care" , Scott Meyers 提出了一个问题,为什么在 C++11/C++14 标准中有关于 auto
和大括号初始化器的特殊规则(他的问题从 at 36m05s 开始)。
auto 与 braced-init-list 组合的语义在§7.1.6.4/6 中定义。
我想了想,也想不出一个用例。到目前为止,我所看到的最接近的例子是 Bjarne Stroustrup 使用它的一个例子。
在他的Cpp 2014 talk "Make Simple Tasks Simple!" ,他曾经使用 auto
来捕获初始化器(但只是作为一种变通方法)。
这是代码(幻灯片 30 的一部分,at 37m10s):
// auto ss1 = collect({ 1, 2, 3, 4, 5, 6 }, odd); // error: Bummer!
auto lst = { 1, 2, 3, 4, 5, 6 };
auto ss2 = collect(lst, odd); // {1,3,5}
但请注意,这只是一种解决方法。他提到应该没有必要。相反,他更愿意直接将参数传递给函数。因此,它不能真正作为 auto
和初始化列表的良好动机。
我对 C++ 的理解不够深入,无法判断在 Bjarne 的示例中允许初始化列表的缺点,正如他所建议的那样。无论如何,在那种情况下它会避免对 auto
的需要。
那么,auto
和 initializer list 是否只是解决一些本来可以更好解决的问题的变通方法?或者有很好的例子,§7.1.6.4/6 中的额外自动扣除规则有用吗?
最佳答案
基本原理在 N2640 中,它一般希望禁止从花括号初始化列表中推导普通类型参数:
template<class T> void inc(T, int); // (1) template<class T> void inc(std::initializer_list<T>, long); // (2) inc({1, 2, 3}, 3); // Calls (2). (If deduction had succeeded // for (1), (1) would have been called — a // surprise.)
但是为 auto
开辟了一个特殊的异常(exception):
On the other hand, being able to deduce an
initializer_list<X>
forT
is attractive to allow:auto x = { 1, 1, 2, 3, 5 }; f(x); g(x);
which was deemed desirable behavior since the very beginning of the EWG discussions about initializer lists. Rather than coming up with a clever deduction rule for a parameter type
T
matched with a {}-list (an option we pursued in earlier sketches and drafts of this paper), we now prefer to handle this with a special case for "auto" variable deduction when the initializer is a {}-list. I.e., for the specific case of a variable declared with an "auto" type specifier and a {}-list initializer, the "auto" is deduced as for a functionf(initializer_list<T>)
instead of as for a functionf(T)
.
关于c++ - 为什么在 C++11/C++14 中有针对自动和大括号初始化器的特殊类型推导规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29565080/