为什么在 C++11/C++14 中对自动和花括号初始化器有特殊的类型推导规则? [英] Why is there a special type deduction rule for auto and braced initializers in C++11/C++14?

查看:24
本文介绍了为什么在 C++11/C++14 中对自动和花括号初始化器有特殊的类型推导规则?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在他的 CppCon 2014 talke 类型推断和你关心的原因"中,Scott Meyers 提出了一个问题,为什么在 C++11/C++14 标准中有关于 auto 和花括号初始化器的特殊规则(他的问题以 在 36m05s).

§7.1.6.4/6 中定义了 auto 与花括号初始化列表结合的语义.

<小时>

我想了想,也想不出用例.到目前为止,我看到的最接近的事情是 Bjarne Stroustrup 使用它的一个例子.

在他的 Cpp 2014 演讲让简单的任务变得简单!"中,他曾经使用auto 捕获初始化程序(但仅作为一种解决方法).

这是代码(第 30 张幻灯片的一部分,在 37m10s):

//auto ss1 = collect({ 1, 2, 3, 4, 5, 6 },odd);//错误:无赖!自动 lst = { 1, 2, 3, 4, 5, 6 };自动 ss2 = 收集(lst,奇数);//{1,3,5}

但请注意,这只是一种解决方法.他提到应该没有必要.相反,他更愿意直接将参数传递给函数.因此,它不能真正成为 auto 和初始化列表的良好动机.

<小时>

我对 C++ 的理解不够深入,无法判断在 Bjarne 的示例中允许初始化列表的缺点,正如他所提议的.无论如何,在这种情况下它会避免对 auto 的需要.

那么,auto 和初始值设定项列表是否只是本可以更好解决的问题的解决方法?或者有没有很好的例子,§7.1.6.4/6 中的额外自动扣除规则是有用的?

解决方案

理由在 N2640,它希望禁止从大括号初始化列表中推导出普通类型参数:

<块引用>

templatevoid inc(T, int);//(1)模板void inc(std::initializer_list, long);//(2)inc({1, 2, 3}, 3);//调用 (2).(如果扣除成功//for (1), (1) 会被调用——a//惊喜.)

但是为auto 开辟了一个特殊的例外:

<块引用>

另一方面,能够推导出initializer_listT 很吸引人:

auto x = { 1, 1, 2, 3, 5 };f(x);g(x);

从一开始就被认为是可取的行为EWG 关于初始化列表的讨论.而不是想出一个与 {}-list 匹配的参数类型 T 的巧妙推导规则(我们在本文早期的草图和草稿中追求的一个选项),我们现在更喜欢用自动"变量的特殊情况来处理这个当初始值设定项是 {}-list 时的推导.即,对于特定的使用auto"类型说明符和一个声明的变量的情况{}-list 初始值设定项,推导出auto"作为函数f(initializer_list) 而不是函数 f(T).

In his CppCon 2014 talke "Type Deduction and Why You Care", Scott Meyers raises the question why there is a special rule about auto and braced initializers in the C++11/C++14 standard (his question starts at 36m05s).

The semantic of auto in combination with a braced-init-list is defined in §7.1.6.4/6.


I thought about it and could not come up with a use-case either. The closest thing that I have seen so far is one example where Bjarne Stroustrup used it.

In his Cpp 2014 talk "Make Simple Tasks Simple!", he once uses auto to capture initializers (but only as a workaround).

Here is the code (part of slide 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}

But note that it is only a workaround. He mentioned that it should not be necessary. Instead he would prefer to directly pass the arguments to the function. So, it cannot really serve as a good motivation for auto and initializer lists.


My understanding of C++ is not deep enough to judge the downsides of allowing initializer-lists in Bjarne's example, as he proposes. Anyway, it would avoid the need for auto in that case.

So, is auto and initializer list only a workaround for something that could have been better solved? Or are there good examples, where the extra auto deduction rule in §7.1.6.4/6 is useful?

解决方案

The rationale is in N2640, which wanted to ban deduction of a plain type parameter from a braced initializer list in general:

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.)

But carved out a special exception for auto:

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++11/C++14 中对自动和花括号初始化器有特殊的类型推导规则?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆