嵌套闭包传递std::array编译失败:是否违反C++标准?
嵌套闭包场景下
std::array类模板实参推导的编译问题 问题场景
给定如下前置声明:
#include <array> template <typename V> void makeError(V& v) {}
以下代码在MSVC 16.11.13(/std:c++17)编译失败:
int main() { [&]() { std::array bugs{0}; [&]() { makeError(bugs); }; }; return 0; }
报错信息:
main.cpp(9,5): error C2955: 'std::array': use of class template requires template argument list
但相同代码在GCC 10.4(--std=c++17)中可正常编译。
另外,移除内层闭包或外层闭包后的代码:
// 移除内层闭包 int main() { [&]() { std::array bugs{0}; makeError(bugs); }; return 0; }
// 移除外层闭包 int main() { std::array bugs{0}; [&]() { makeError(bugs); }; return 0; }
在MSVC和GCC中均能正常编译。
问题解答
这段代码是有效的C++17代码,MSVC的报错属于编译器实现缺陷,而非代码违反C++标准。
原因分析
- 类模板实参推导(CTAD)规则:C17引入的类模板实参推导允许编译器根据初始化器自动推导类模板的模板参数。对于
std::array bugs{0};,编译器应当推导出模板参数为int(元素类型)和1(数组大小),即实际类型为std::array<int, 1>,这符合C17标准[temp.deduct.class]章节的规定。 - 编译器实现差异:只有在嵌套闭包的场景下,MSVC未能正确完成外层闭包中
std::array变量的CTAD推导,而GCC正确处理了该场景。移除任意一层闭包后两边都能编译,说明这是MSVC在处理嵌套闭包时的推导逻辑漏洞,而非代码本身不符合标准。
内容的提问来源于stack exchange,提问作者Joshua Hyatt
相关产品推荐
相关产品推荐

