【发布时间】:2018-04-15 18:35:42
【问题描述】:
让我们从一个最小的例子开始:
#include <utility>
int main()
{
auto [a, b] = std::pair(1, 'A');
return a;
}
使用 GCC 7.3 编译并传递 -std=c++17 和 -Wunused-variable,并运行它:
<source>: In function 'int main()':
<source>:5:15: warning: unused variable 'b' [-Wunused-variable]
auto [a, b] = std::pair(1, 'A');
^
GCC 可能正确地报告了b 的不使用,但它错误地将其称为变量。引用[dcl.struct.bind]/1:
结构化绑定声明将 identifier-list 的 identifiers v0、v1、v2……作为结构化绑定的名称 ([basic.scope.declarative]) .
所以b 显然不是一个变量,而是一个名称。使用 Clang 6.0.0 和相同的标志编译相同的代码,我们不会收到任何警告。从代码中删除return a; 语句:
#include <utility>
int main()
{
auto [a, b] = std::pair(1, 'A');
// return a;
}
然后用 Clang 再次编译,我们得到:
<source>:5:10: warning: unused variable '[a, b]' [-Wunused-variable]
auto [a, b] = std::pair(1, 'A');
^
根据我的解释,它正确地将[a, b] 视为变量,而将a 和b 分别视为名称。 我的问题然后是考虑到变量实际上是在第一个代码的return a; 语句中使用的,为什么 GCC 会诊断出 b 未使用的警告?
【问题讨论】:
-
什么返回声明?仅返回
a,而不返回b。附言因为这是一个常见的习惯用法,有结构化的绑定,据报道这个警告信息不再由 gcc 8 发出。 -
如果它们不是变量,你怎么能取到它们的地址呢?例如
auto p = &a; -
@NeilButterworth 它们是结构底层成员的名称。实际变量没有得到标识符。
-
它们是名称与它们是变量并不冲突。或者简单地说,它们还能是什么?
-
“为什么 GCC 会诊断结构化绑定的未使用变量,而 Clang 不会?” - 因为编译器是不同的,诊断不同的东西(并且有不同的错误),并且有不同级别的标准一致性。
标签: c++ gcc language-lawyer c++17 structured-bindings