c++ - 为什么在 C++11/C++14 中有针对自动和大括号初始化器的特殊类型推导规则?

标签 c++ c++11 auto c++14 initializer-list

在他的 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> for T 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 function f(initializer_list<T>) instead of as for a function f(T).

关于c++ - 为什么在 C++11/C++14 中有针对自动和大括号初始化器的特殊类型推导规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29565080/

相关文章:

c++ - 为什么不基于 const range 来使用 const_iterator?

c++ - 如何知道安装了哪个版本的 firefox?

c++ - 为什么string_view::operator ==按值接受参数

c++ - 我的对象在 vector 中的地址发生变化

c++ - 函数 typedef 的 using 等价物是什么?

C++:在 "auto"的二维数组上嵌套 For 循环

c++ - 可以返回兄弟对象的函数的自动返回类型

c++ - std::ref 和 swap 函数似乎不能很好地协同工作

c++ - 为什么Qt设计器生成的对象总是分配在堆中?

C++ 使用 const 数组和 initializer_list 重载构造函数