是否使用“auto"进行声明?匹配使用具体类型说明符的 extern 声明? [英] Does a declaration using "auto" match an extern declaration that uses a concrete type specifier?

查看:31
本文介绍了是否使用“auto"进行声明?匹配使用具体类型说明符的 extern 声明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下程序:

extern int x;自动 x = 42;int main() { }

Clang 3.5 接受(现场演示),GCC 4.9 和 VS2013 不接受(前者的现场演示).谁是对的,C++ 标准中规定的正确行为在哪里?

解决方案

令人惊讶的是,标准中几乎没有这方面的内容.我们听到的关于重新申报的所有信息是:

<块引用>

[C++11: 3.1/1]: 声明(第 7 条)可以将一个或多个名称引入翻译单元或重新声明由先前声明引入的名称.[..]

以及auto语义的唯一相关部分:

<块引用>

[C++11: 7.1.6.4/3]: 否则,从其初始值设定项推导出变量的类型.[..]

(提醒我们x 的类型是int).

我们知道变量必须被所有声明赋予相同的类型:

<块引用>

[C++11: 3.5/10]: 所有类型调整后(在此期间typedefs(7.1.3)被其定义替换),所有指定的类型引用给定变量或函数的声明应该是相同的,除了数组对象的声明可以指定不同的数组类型,因为存在或不存在主数组边界(8.3.4).违反此类型标识规则不需要诊断.

和类型的所有调整后"应该处理有关auto参与所有这些的任何问题;那么,我的解释是这本质上是 x 在全局范围内的有效重新声明(和定义),类型为 int,并且 Clang 是正确的.即使我们建议 auto 不算作类型调整",因为不需要诊断,最坏的情况是所有列出的实现都以自己的方式兼容.>

我相信 GCC 和 Visual Studio 的灵感来自以下几点:

<块引用>

[C++11: 7.1.6.4/5]: 在本节未明确允许的上下文中使用 auto 的程序是格式错误的.

…但我认为这是短视的.标准语言似乎不太可能禁止通常的重新声明规则,仅仅因为它们没有在 7.1.6.4 中重复或明确引用.

C++14 添加了与具有推导类型的函数声明相关的措辞:

<块引用>

[C++14: 7.1.6.4/13]: 使用占位符类型声明返回类型的函数或函数模板的重新声明或特化也应使用该占位符,而不是推断类型.[..]

根据对称性,人们可能会认为,在您的 int 情况下,GCC 和 VS 拒绝该程序是正确的.然而,这是一个不同的特性(因为推导不能应用于仅仅声明),因此是一个不同的场景.

无论如何,改进的标准措辞在这里都会有所帮助.我认为这是一个[相当轻微的]编辑缺陷.

Consider the following program:

extern int x;
auto x = 42;
int main() { }

Clang 3.5 accepts it (live demo), GCC 4.9 and VS2013 do not (live demo for the former). Who is right, and where is the correct behavior specified in the C++ Standard?

解决方案

There's surprisingly little in the standard about this. About all we hear about redeclaration is:

[C++11: 3.1/1]: A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations. [..]

and the only relevant part of auto's semantics:

[C++11: 7.1.6.4/3]: Otherwise, the type of the variable is deduced from its initializer. [..]

(reminding us that the type of x is int).

We know that a variable must be given the same type by all declarations:

[C++11: 3.5/10]: After all adjustments of types (during which typedefs (7.1.3) are replaced by their definitions), the types specified by all declarations referring to a given variable or function shall be identical, except that declarations for an array object can specify array types that differ by the presence or absence of a major array bound (8.3.4). A violation of this rule on type identity does not require a diagnostic.

and the "after all adjustments of types" ought to take care of any questions regarding auto's participation in all of this; my interpretation, then, is that this is inherently a valid redeclaration (and definition) of the x at global scope with type int, and that Clang is correct. Even if we propose that auto does not count as "adjustment of type", since no diagnostic is required, at worst all listed implementations are compliant in their own way.

I believe GCC and Visual Studio are taking the following as inspiration:

[C++11: 7.1.6.4/5]: A program that uses auto in a context not explicitly allowed in this section is ill-formed.

…but I think that this is short-sighted. It seems unlikely that the standard language is intended to prohibit the usual redeclaration rules, just because they are not repeated or explicitly referenced from within 7.1.6.4.

C++14 adds wording that relates to declarations of functions with deduced types:

[C++14: 7.1.6.4/13]: Redeclarations or specializations of a function or function template with a declared return type that uses a placeholder type shall also use that placeholder, not a deduced type. [..]

By symmetry one might suggest that, in your int case, it is intended that GCC and VS be correct in rejecting the program. However, this is a different feature (since deduction cannot be applied to mere declarations) and thus a different scenario.

Either way, improved standard wording would help here. I consider it a [reasonably minor] editorial defect.

这篇关于是否使用“auto"进行声明?匹配使用具体类型说明符的 extern 声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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