为什么C++;不允许在一个自动语句中使用多个类型? 2011 C++标准引入了新的关键字 Audio/Cuff>,它可以用来定义变量而不是类型,即 auto p=make_pair(1,2.5); // pair<int,double> auto i=std::begin(c), end=std::end(c); // decltype(std::begin(c))
当为什么C++;不允许在一个自动语句中使用多个类型? 2011 C++标准引入了新的关键字 Audio/Cuff>,它可以用来定义变量而不是类型,即 auto p=make_pair(1,2.5); // pair<int,double> auto i=std::begin(c), end=std::end(c); // decltype(std::begin(c)),c++,c++11,for-loop,auto,C++,C++11,For Loop,Auto,当x为不同类型时我的问题:为什么标准不允许最后一行?可以通过解释auto来允许它,而不是表示某些要被删除的类型,而是表示任何声明的auto变量的类型应从其赋值中推导出来。C++11标准有什么理由不遵循这种方法吗 实际上,这有一个用例,即在for循环的初始化语句中: for(auto i=std::begin(c), end=std::end(c), x=*i; i!=end; ++i, x+=*i) { ... } 当变量i、end和x的范围限于for循环时。除非这些变量有一个公共类型,否
x
为不同类型时我的问题:为什么标准不允许最后一行?可以通过解释auto
来允许它,而不是表示某些要被删除的类型,而是表示任何声明的auto
变量的类型应从其赋值中推导出来。C++11标准有什么理由不遵循这种方法吗
实际上,这有一个用例,即在for
循环的初始化语句中:
for(auto i=std::begin(c), end=std::end(c), x=*i; i!=end; ++i, x+=*i)
{ ... }
当变量i
、end
和x
的范围限于for
循环时。除非这些变量有一个公共类型,否则C++不能实现这一点。strong>这是否正确?(排除了将所有类型放入结构中的丑陋技巧)
在一些可变模板应用中也可能有用例。
< P>如果引用C++ 2014工作草案,则标准允许这样的代码。
auto x = 5, *y = &x; // OK: auto is int
我想补充一点,在您的示例中,无法推断自动,因为迭代器类型和迭代器的值类型是两种不同的类型。根据此功能的最终版本,可能的多声明器自动
实现如下:(来自第6节)
我们相信有可能实现一致的形式和效果
一贯的行为。我们通过插入(为了
exposition)中间类型定义,并应用
此类型在“仿佛”扩展中保持一致:
我们不仅通过这样一种方式实现了形式和行为的一致性
通过协调表述,我们还可以解决更复杂的情况。
例如,当前导声明符包括ptr运算符时:
我们的公式附加语义,如同声明:
如此可能的实现所示,更改类型将无效,因此将导致错误。
此功能是以这种方式实现的,因为否则它将不同于其他类型的多变量声明。
我记得看到一场关于是否允许更改类型的讨论,但我不记得在哪里。IIRC,他们决定这将更难实现,但另一个原因可能是因为他们无法就何时选择不同类型(新行为)或何时隐式转换为第一个声明变量的推导类型(旧行为)达成共识而放弃了它.我认为这只是一个与非
自动声明的一致性问题
这:
相当于:
int n = 42, *p = &n;
其中,类型int
和int*
来自初始值设定项。在这两种情况下,尽管int
和int*
是不同的类型,但由于它们的语法关系密切,允许它们位于同一个声明中。通过“声明遵循使用”规则,C和C++声明几乎遵循,您定义的是“代码> N<代码/代码>和<代码> *P<代码>类型为<代码> int
可以在同一声明中允许不相关的类型:
auto n = 42, x = 1.5;
但上述声明必须相当于两个单独的声明:
int n = 42; double x = 1.5;
我认为添加auto
的想法是对语言进行最小的更改,允许从初始值设定项推断类型,但不改变可能的声明类型
即使没有auto
,也可以在循环头的中定义int
和int*
:
for (int n = 42, *p = &n; expr1; expr2) { /* ... / }
但是不能同时声明int
和double
。添加auto
并没有改变这一点
在for
循环的上下文之外,通常最好使用单独的声明。在大多数情况下,将大量不同的声明推入for
循环可能是一个坏主意。对于需要大量声明的(可能很少)情况,您可以将它们放在循环之上,如下所示:
auto i=std::begin(c), end=std::end(c),
for( x=*i; i!=end; ++i, x+=*i) {
// ...
}
如果要限制范围,请在整个事件周围添加另一组{
}
。(在这种情况下,您可能希望end
成为const
。C++17最终带来了结构化绑定声明,解决了您的问题:
auto [ i, s, f ] = std::tuple(42, "Hello World", 5.0);
这将i声明为整数42,s声明为以零结尾的字符串“Hello World”,s声明为常量char*
,f声明为双精度数字5.0
我不知道没有中间std::tuple
的解决方案。如果使用完全一致的C++20编译器,还可以使用别名模板缩写std::tuple
,如本例所示:
template<typename ... ARGS> using T = std::tuple<ARGS ...>;
auto [ i, s, f ] = T(42, "Hello World", 5.0);
使用T=std::tuple的模板;
自动[i,s,f]=T(42,“你好世界”,5.0);
这可以在C++17和C++20模式下使用
g++-10
很好地编译,尽管它实际上应该只在C++20模式下编译。C++17不允许对别名模板进行模板参数推断,即使在最简单的情况下,模板参数列表以1:1的比例转发到别名模板。几乎所有形式为“标准为什么说废话”的问题都有以下答案之一:1)与C的向后兼容性,2)他们没有时间做其他事情,3)[在这里插入未经证实的意见]@JohnDibling我不同意。通常有很好的理由(除了向后兼容性,这里似乎不适用)。我想知道这里是否有充分的理由。约翰是对的。几乎所有这样的问题最终都会得到这样的答案。他不是说有充分的理由这么做
int n = 42; double x = 1.5;
for (int n = 42, *p = &n; expr1; expr2) { /* ... / }
auto i=std::begin(c), end=std::end(c),
for( x=*i; i!=end; ++i, x+=*i) {
// ...
}
auto [ i, s, f ] = std::tuple(42, "Hello World", 5.0);
template<typename ... ARGS> using T = std::tuple<ARGS ...>;
auto [ i, s, f ] = T(42, "Hello World", 5.0);