我有这样的代码:
template<class ListItem>
static void printList(QList<ListItem>* list)
{
for (auto i = list->size() - 1, j = -1; i >= 0; --i) {
std::cout << i << ", " << j << ": " << list->at(i) << std::endl;
}
}
当我用 g++ 6.2.1 编译它时,我得到以下编译器输出:
test.cpp: In function ‘void printList(QList<T>*)’:
test.cpp:10:7: error: inconsistent deduction for ‘auto’: ‘auto’ and then ‘int’
for (auto i = list->size() - 1, j = -1; i >= 0; --i) {
^~~~
如果变量具有不同的类型,例如 auto i = 0.0, j = 0;
,我会理解,但在这种情况下,list 是指向 QList 的指针,它的 size() 方法返回 int
, -1
本身也应该是 int
。错误信息也有点奇怪。
变量 i
和 j
仅在此循环中需要,我想将它们声明为循环参数。键入 int
而不是 auto 并不难,但我想知道:auto
是否不应该用于一次性声明多个变量,或者我是这里遗漏了一些东西,这确实是错误的代码,或者是编译器的错误?
附:看起来使用模板函数是这里的关键部分,将循环从模板中分解出来不会产生错误。那么,更像是编译器中的一个错误?
最佳答案
这是 GCC 中的一个错误。
根据[dcl.spec.auto]/1:
The
auto
anddecltype(auto)
type-specifiers are used to designate a placeholder type that will be replaced later by deduction from an initializer. [...]
模板参数推导的规则永远不会将类型推导出为 auto
。这种情况下推导的目的其实就是替换 auto
为推导的类型。
在例子中,list
有一个依赖类型(它依赖于模板参数ListItem
),所以表达式list->size() - 1
也有一个依赖类型,这使得 i
的类型也依赖,这意味着它只会在函数模板 printList
的实例化时被解析。只有这样才能检查与该声明相关的其他语义约束。
根据[temp.res]/8:
Knowing which names are type names allows the syntax of every template to be checked. The program is ill-formed, no diagnostic required, if:
[... long list of cases of which none applies here ...]
Otherwise, no diagnostic shall be issued for a template for which a valid specialization can be generated. [ Note: If a template is instantiated, errors will be diagnosed according to the other rules in this Standard. Exactly when these errors are diagnosed is a quality of implementation issue. — end note ]
(强调我的)
GCC 在分析模板 printList
的定义时发出该错误是错误的,因为可以生成明显有效的模板特化。事实上,如果 QList
没有任何 size()
返回 int
以外的特化,则 i 的声明
和 j
将在 printList
的所有实例中有效。
所有报价均来自N4606 ,(几乎)当前的工作草案,但上述引用的相关部分自 C++14 以来没有改变。
更新:Confirmed as a regression在 GCC 6/7 中。感谢 T.C.用于错误报告。
更新:原始错误 (78693) 已在即将发布的 6.4 和 7.0 版本中修复。它还发现了 GCC 处理此类构造的方式的一些其他问题,导致另外两个错误报告:79009和 79013 .
关于c++ - 使用 C++11 auto 关键字声明两个(或更多)变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40841777/