使用C++ 11 auto关键字声明两个(或更多)变量

dro*_*ngo 25 c++ templates auto c++11

我有这样的代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

当我用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) {
       ^~~~
Run Code Online (Sandbox Code Playgroud)

我理解这一点,如果变量有不同的类型auto i = 0.0, j = 0;,但在这种情况下,list是一个指向QList的指针,并且它的size()方法返回int,-1它本身也应该是int.错误消息也有点奇怪.

变量ij只需要在这个循环中,我想向他们声明为循环参数.输入并不难int自动,但我想知道:auto不应该用于一次声明多个变量,或者我在这里遗漏了一些东西而且它确实是错误的代码,或者它可能是编译器的错误?

PS看起来像使用模板函数是这里的关键部分,将循环从模板中分解出来不会产生错误.那么,更像是编译器中的错误?

现场演示 - 最少的代码

bog*_*dan 13

这是GCC中的一个错误.

根据[dcl.spec.auto]/1:

autodecltype(auto) 类型SPECI音响ERS用于指定将在后面通过扣除从一个初始化替换的占位符类型.[...]

模板参数推导的规则从不推断出类型auto.在这种情况下,扣除的目的实际上是用推断的类型替换 auto.

在示例中,list具有依赖类型(它取决于模板参数ListItem),因此表达式list->size() - 1也具有依赖类型,这使得类型i也依赖,这意味着它只会在实例化函数模板时解析printList.只有这样才能检查与该声明相关的其他语义约束.

根据[temp.res]/8:

知道哪些名称是类型名称允许检查每个模板的语法.如果出现以下情况,该计划格式错误,无需诊断:

[......这里没有适用的案例清单......]

否则,不能为可以生成有效特化的模板发出诊断.[ 注意:如果实例化模板,将根据本标准中的其他规则诊断错误.确切地说,这些错误被诊断出来是一个实施质量问题.- 结束说明 ]

(强调我的)

在分析模板的定义时,GCC发出错误是错误的printList,因为可以生成明确有效的模板特化.实际上,如果QList没有任何size()返回其他内容的特化int,则声明ij将在所有实例化中有效printList.


所有引用均来自N4606,(几乎)当前的工作草案,但上面引用的相关部分自C++ 14以来没有改变.


更新:在GCC 6/7中确认为回归.感谢TC提供错误报告.

更新:原始错误(78693)已修复即将发布的6.4和7.0版本.它还揭示了GCC处理此类构造的方式的其他一些问题,导致另外两个错误报告:7900979013.