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.错误消息也有点奇怪.
变量i和j只需要在这个循环中,我想向他们声明为循环参数.输入并不难int自动,但我想知道:auto不应该用于一次声明多个变量,或者我在这里遗漏了一些东西而且它确实是错误的代码,或者它可能是编译器的错误?
PS看起来像使用模板函数是这里的关键部分,将循环从模板中分解出来不会产生错误.那么,更像是编译器中的错误?
bog*_*dan 13
这是GCC中的一个错误.
根据[dcl.spec.auto]/1:
的
auto和decltype(auto)类型SPECI音响ERS用于指定将在后面通过扣除从一个初始化替换的占位符类型.[...]
模板参数推导的规则从不推断出类型auto.在这种情况下,扣除的目的实际上是用推断的类型替换 auto.
在示例中,list具有依赖类型(它取决于模板参数ListItem),因此表达式list->size() - 1也具有依赖类型,这使得类型i也依赖,这意味着它只会在实例化函数模板时解析printList.只有这样才能检查与该声明相关的其他语义约束.
根据[temp.res]/8:
知道哪些名称是类型名称允许检查每个模板的语法.如果出现以下情况,该计划格式错误,无需诊断:
[......这里没有适用的案例清单......]
否则,不能为可以生成有效特化的模板发出诊断.[ 注意:如果实例化模板,将根据本标准中的其他规则诊断错误.确切地说,这些错误被诊断出来是一个实施质量问题.- 结束说明 ]
(强调我的)
在分析模板的定义时,GCC发出错误是错误的printList,因为可以生成明确有效的模板特化.实际上,如果QList没有任何size()返回其他内容的特化int,则声明i和j将在所有实例化中有效printList.
所有引用均来自N4606,(几乎)当前的工作草案,但上面引用的相关部分自C++ 14以来没有改变.
更新:原始错误(78693)已修复即将发布的6.4和7.0版本.它还揭示了GCC处理此类构造的方式的其他一些问题,导致另外两个错误报告:79009和79013.