为什么C++在一个自动语句中不允许多种类型?

Wal*_*ter 13 c++ for-loop auto c++11

2011 C++标准引入了new关键字auto,可用于定义变量而不是类型,即

auto p=make_pair(1,2.5);                   // pair<int,double>
auto i=std::begin(c), end=std::end(c);     // decltype(std::begin(c))
Run Code Online (Sandbox Code Playgroud)

在第二行中,i并且end具有相同的类型,被称为的auto.该标准不允许

auto i=std::begin(container), e=std::end(container), x=*i;
Run Code Online (Sandbox Code Playgroud)

什么时候x会有不同的类型.我的问题:为什么标准不允许这最后一行?可以通过将其解释auto为不代表某些待定的类型,而是指示所声明的任何变量的类型auto应从其指定值推导出来.C++ 11标准有没有很好的理由不遵循这种方法?

实际上有一个用例,即在for循环的初始化语句中:

for(auto i=std::begin(c), end=std::end(c), x=*i;  i!=end;  ++i, x+=*i)
{ ... }
Run Code Online (Sandbox Code Playgroud)

当变量的范围i,end以及x被限制在for环路.AFAIK,除非这些变量具有通用类型,否则无法在C++中实现.它是否正确?(将所有类型放入struct排除的丑陋技巧)

在一些可变参数模板应用程序中也可能存在用例.

Kei*_*son 9

我认为这只是与非auto声明的一致性问题.

这个:

auto n = 42, *p = &n;
Run Code Online (Sandbox Code Playgroud)

相当于:

int n = 42, *p = &n;
Run Code Online (Sandbox Code Playgroud)

其中的类型intint*派生自初始化器.在这两种情况下,即使intint*有不同的类型,他们允许在相同的声明,因为他们的亲密关系句法的.(由"声明如下方式使用"规则,C和C++声明几乎跟随,你定义都n*p为类型的int.)

可以在同一声明中允许不相关的类型:

auto n = 42, x = 1.5;
Run Code Online (Sandbox Code Playgroud)

但上述内容必须相当于两个单独的声明:

int n = 42; double x = 1.5;
Run Code Online (Sandbox Code Playgroud)

我认为添加时的想法auto是对语言进行最小的更改,允许从初始化程序推断类型,但不能更改可能的声明类型.

即使没有auto,您也可以在循环标题中定义一个int和一个:int*for

for (int n = 42, *p = &n; expr1; expr2) { /* ... / }
Run Code Online (Sandbox Code Playgroud)

但你不能一起声明一个int和一个double.添加auto简单并没有改变这一点.

for循环的上下文之外,无论如何使用单独的声明通常要好得多.for在大多数情况下,将许多不同的声明推入循环可能是一个坏主意.对于需要大量声明的(可能是罕见的)情况,你可以将它们放在循环之上,如下所示:

auto i=std::begin(c), end=std::end(c),
for( x=*i;  i!=end;  ++i, x+=*i) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

{ }如果要限制范围,请添加另一组整个事物.(在这种情况下,你可能想end成为const反正.)

  • 如果`auto`按照你规定的方式工作,那么`auto x = 1.5,y = 0;`将具有不同的含义`double x = 1.5,y = 0;` (3认同)

JKo*_*Kor 5

根据该特征的公认提案N1737的最终修订,可能的多声明器auto实现如下:(来自第6节)

我们相信可以实现一致的形式和一致的行为.我们通过插入(为了展示的目的)中间__Deduced_type定义,并在as-if扩展中一致地应用此类型来实现:

  // Listing 12
 typedef int __Deduced_type; // exposition only
  __Deduced_type a = 1;
 // decltype(a) is int
 __Deduced_type b = 3.14; // decltype(b) is int
  __Deduced_type * c = new float; // error; decltype(c) would be int *
Run Code Online (Sandbox Code Playgroud)

通过这种协调的表述,我们不仅可以实现形式和行为的一致性,还可以解决更复杂的情况.例如,当主要声明符包含ptr-operator时:

 // Listing 13 
auto * a = new int(1), b = 3.14, * c = new float;
Run Code Online (Sandbox Code Playgroud)

我们的配方附加了语义 - 如果声明:

// Listing 14 
 typedef int __Deduced_type; // exposition only
 __Deduced_type * a = new int(1); // decltype(a) is int *
 __Deduced_type b = 3.14; // decltype(b) is int
 __Deduced_type * c = new float; // error; decltype(c) would be int *
Run Code Online (Sandbox Code Playgroud)

如此可能的实现所示,更改类型将无效,因此会导致错误.
此功能以这种方式实现,因为否则它将与其他类型的多变量声明不同.
我记得看到有关是否允许更改类型的讨论,但我不记得在哪里.IIRC,他们认为实施起来会更难,但另一个原因可能是它被删除了,因为他们无法就何时选择不同类型(新行为)或何时隐式转换为推导类型达成共识第一个声明的变量(旧行为).