实现与C++标准的一致性对于Visual C++团队来说是一条漫长的道路。如果您最近在任何会议上看到我们,您可能已经看到了MSVC一致性幻灯片(你可以拿一份幻灯片或观看2017年CppCon演讲 在这里 完成这个幻灯片上的特性——包括C++ 11、C++ 14和C++ 17的特性——这是我们团队在过去几年中的主要目标之一。
我们很高兴地宣布,在Visual Studio 2017 15.7版中,我们实现了这些功能(技术规范正在进行中,因为它们正在进入标准。)
VisualStudio版本15.7中的MSVC编译器工具集符合C++标准!
我们不会停止我们的一致性努力——总是有新的特性、缺陷报告等等。在这些特征中有一些地方我们知道错误,但是我们相信,在这一点上,C++标准中没有应该用MSVC编译器避免的特征区域(除了下面描述的预处理器)之外,以及浮点
达到一致性
我们的编译器历史悠久: 二月是Visual C++产品第二十五周年 . 这个 Visual C++内置的微软C产品已有35年历史。 . 在编译器的整个历史中,我们首先关心的是保持兼容性,这样代码就不会被破坏。 我们仔细记录了为符合性所做的所有更改 ,使我们的修复程序在可能的情况下与源代码兼容,并在需要更改代码时提供解决方法。三年前, 我们公布了我们的编译器重写 . 我们已经在一个我们称之为“复兴”的过程中对编译器进行了一次大修。旧的YACC解析器和“Rejuv”递归下降解析器在我们今天的编译器中并排运行。当我们能够实现它们时,我们已经将特性从旧代码单独移动到“Rejuv”代码。这项技术使我们能够不断取得进展,同时尽量减少破坏性的变化。重写特性有时会导致一些倒退,对于给您带来的不便,我们深表歉意。然而,总体上,在现代编译器上实现现代C++特性比在我们几十年前的解析器上要容易得多,其中一些功能无法完全实现。
标准库一致性
标准库的MSVC实现最近获得了一些主要的新特性:并行算法、文件系统、constexpr字符特性、特殊数学以及对类模板参数推导的支持。我们的功能状态的详细表格如下所示。
编译器一致性
使用VisualStudio 2017版本15.7,我们将完全实现C++标准中几乎所有的功能,包括通过C++ 17实现的所有版本。其余的功能已经实现(并且将很快装运)或正在实施。这包括完成了一些我们从C++ 11/14中所做的更困难的功能:两阶段名称查找,表达式sFANEA,扩展 constexpr
,并打包扩展。每一个编译器都有bug我们在其他实现中报告了一些一致性bug,同时用新的眼光实现了旧的特性。我们将继续解决我们的缺陷,并继续实现新的特性,因为它们在标准草案中被采用。
技术规格
MSVC在许多技术规范方面也处于领先地位。MSVC拥有最完整的 模块TS的C++扩展 . 我们有最古老的 协同程序的C++扩展 最近我们重新编写了用于协同程序的优化器。微软正在推出大量同时使用模块和协同程序的产品。我们一直在研究 范围TS的C++扩展 ,以改善TS,并使MSVC达到我们可以支持的范围。而大多数 概念的C++扩展 已经被合并到C++ 20标准草案中,我们致力于在C++ 20工作中尽早实现该功能。
“但是……呢?”
我们将重点放在流行的OSS库上,同时保持大型代码库的源代码兼容性,从而推动了我们的一致性工作。一些主要的库仍然不能用MSVC正确地编译,我们正在积极地研究它们。
- 助推。Hana:
- 扩展
constexpr
在我们的编译器中也是一个挑战。我们有一些已知的bug,但是我们相信我们的实现是一致的。作为一个具体的例子,我们发现了大约10个阻塞constexpr
编译时的错误 Boost Hana,“元编程标准库” . 在我们积极修复这些编译器错误的同时,如果我们将源代码变通方法更改应用到Hana,那么我们可以通过大约30-40%的Hana测试。我们目前正在完全重写constexpr求值器,以解决剩下的问题。
- 扩展
- 包装扩展:
- 包扩展很快成为C++的结构。我们的实现也在发展,因为我们移动构造来使用新的“复兴”编译器解析树。我们在可变的通用lambda、数组上的包扩展和函数模板的偏序方面有一些缺陷,这些缺陷将通过使用新的解析树来解决。我们也在修复 重写继承构造函数 正确使用包扩展。
- 范围V3:
- 预处理器:
- 一如既往,在 开发者社区门户 将被视为和响应的Visual C++团队。
功能状态表
以下是Stephan T准备的特性状态表和注释。Lavavej(没有通常的颜色突出显示)。
C++ 11/14核心语言特点 | 状态 | 纸类 | 笔记 |
[其他一切] | VS 2017年 | [抛出()] | |
两阶段名称查找 | 与2017年15.7 | [两阶段] | |
表达SFINAE | 与2017年15.7 | N2634型 | [解释] |
C99预处理器 | 部分 | 1653号 | [预处理器] |
C++ 17核心语言特点 | 状态 | 纸类 | 笔记 |
删除三角图 | 与2010年相比 | N4086型 | [14] |
带大括号的自动初始化列表的新规则 | 与2015年相比 | 编号3922 | [14] |
模板参数中的typename | 与2015年相比 | N4051号 | [14] |
名称空间和枚举数的属性 | 与2015年相比 | N4266号 | [14] |
u8字符文本 | 与2015年相比 | 编号4267 | [14] |
忽略无法识别的属性 | 与2015年相比 | P0283R2型 | [14] |
嵌套命名空间定义 | 与2015.3相比 | N4230型 | |
简洁的静态断言 | VS 2017年 | 编号3928 | |
基于广义范围的for循环 | VS 2017年 | P0184R0型 | [14] |
[[fallthrough]]属性 | VS 2017年 | P0188R1型 | |
删除register关键字 | 与2017年15.3 | P0001R1型 | |
删除bool的运算符++ | 与2017年15.3 | P0002R1型 | |
按价值捕获 | 与2017年15.3 | P0018R3型 | |
不重复地使用属性名称空间 | 与2017年15.3 | P0028R4型 | |
__你是否包括 | 与2017年15.3 | P0061R1型 | [14] |
整数固定枚举的直接列表初始化 | 与2017年15.3 | P0138R2型 | |
constexpr lambdas公司 | 与2017年15.3 | P0170R1型 | |
[[nodiscard]]属性 | 与2017年15.3 | P0189R1型 | |
[[maybeu unused]]属性 | 与2017年15.3 | P0212R1型 | |
结构化绑定 | 与2017年15.3 | P0217R3型 | |
constexpr if语句 | 与2017年15.3 | P0292R2型 | [ifConstexpr] |
带初始值设定项的选择语句 | 与2017年15.3 | P0305R1型 | |
允许更多非类型模板参数 | 与2017年15.5 | N4268号 | |
折叠表达式 | 与2017年15.5 | N4295型 | 和P0036R0 |
删除动态异常规范 | 与2017年15.5 | P0003R5型 | |
向类型系统添加noexcept | 与2017年15.5 | P0012R1型 | |
过对齐动态内存分配 | 与2017年15.5 | P0035R4型 | |
十六进制浮点文字 | 与2017年15.5 | P0245R1型 | |
内联变量 | 与2017年15.5 | P0386R2型 | |
将模板参数与兼容参数匹配 | 与2017年15.5 | P0522R0型 | |
保证副本省略 | 与2017年15.6 | P0135R1型 | |
确定资格转换 | 与2017年15.7 | N4261号 | |
扩展聚合初始化 | 与2017年15.7 | P0017R1型 | |
类模板参数推导 | 与2017年15.7 | P0091R3型 | 和P0512R0 |
用auto声明非类型模板参数 | 与2017年15.7 | P0127R2型 | |
重写继承构造函数 | 与2017年15.7 | P0136R1型 | |
标准::流槽() | 与2017年15.7 | P0137R1型 | [流槽] |
优化表达式求值顺序 | 与2017年15.7 | P0145R3型 | 和P0400R0 |
使用声明打包扩展 | 与2017年15.7 | P0195R2型 | |
修复初始化器列表构造函数的类模板参数推导 | 与2017年15.7 | P0702R1型 | [医生] |
简化隐式lambda捕获 | 不 | P0588R1型 | [医生] |
CWG1581:何时定义constexpr成员函数? | 不 | P0859R0型 | [医生] |
放宽结构化绑定自定义点查找规则 | 不 | P0961R1型 | [医生] |
放宽循环自定义点查找规则的范围 | 不 | P0962R1型 | [医生] |
允许结构化绑定到可访问的成员 | 不 | P0969R0型 | [医生] |
状态 | 标准 | 纸类 | 职务 | 笔记 |
部分15.7 | C++ 17 | P0067R5型 | 基本字符串转换 | [字符转换] |
与2017年15.7 | C++ 20 | P0777R1型 | 避免不必要的腐烂 | [14] |
与2017年15.7 | C++ 17 | P0024R2型 | 并行算法 | [平行] |
与2017年15.7 | C++ 17 | P0030R1型 | 下压(x,y,z) | |
与2017年15.7 | C++ 17 | P0218R1型 | <文件系统> | |
与2017年15.7 | C++ 17 | P0219R1型 | 文件系统的相对路径 | |
与2017年15.7 | C++ 17 | P0226R1型 | 数学特殊函数 | |
与2017年15.7 | C++ 17 | P0317R1型 | 文件系统的目录项缓存 | |
与2017年15.7 | C++ 17 | P0336R1型 | 重命名并行执行策略 | |
与2017年15.7 | C++ 17 | P0392R0型 | 支持文件系统路径中的字符串视图 | |
与2017年15.7 | C++ 17 | P0394R4型 | 对于异常,并行算法应该终止() | |
与2017年15.7 | C++ 17 | P0426R1型 | 字符特征的constexpr | |
与2017年15.7 | C++ 17 | P0430R2型 | 支持非POSIX文件系统 | |
与2017年15.7 | C++ 17 | P0433R2型 | STL的扣减指南 | |
与2017年15.7 | C++ 17 | P0452R1型 | 统一 |
|
与2017年15.7 | C++ 17 | P0492R2型 | 解析文件系统的NB注释 | |
与2017年15.7 | C++ 17 | P0682R1型 | 修复基本字符串转换 | [医生] |
与2017年15.6 | C++ 17 | … | <内存资源> | |
与2017年15.6 | C++ 17 | P0220R1型 | 图书馆基础V1 | |
与2017年15.6 | C++ 17 | P0337R0型 | 删除多态分配程序分配 | |
与2017年15.6 | C++ 17 | P0739R0型 | STL类模板参数推导的改进 | [医生] |
与2017年15.5 | C++ 17 | P0003R5型 | 删除动态异常规范 | [雷姆] |
与2017年15.5 | C++ 17 | P0005R4型 | 不是u fn() | [折旧] |
与2017年15.5 | C++ 17 | P0033R1型 | 重新编写启用u共享u | [14] |
与2017年15.5 | C++ 17 | P0083R3型 | 拼接地图和集合 | |
与2017年15.5 | C++ 17 | P0174R2型 | 废弃库零件 | [折旧] |
与2017年15.5 | C++ 17 | P0302R1型 | 正在删除std::函数中的分配器支持 | [雷姆] |
与2017年15.5 | C++ 17 | P0358R1型 | 修复notu fn() | |
与2017年15.5 | C++ 17 | P0414R2型 | 共享的u ptr |
[14] |
与2017年15.5 | C++ 17 | P0497R0型 | 修复阵列的共享u ptr | [14] |
与2017年15.5 | C++ 17 | P0508R0型 | 澄清插入返回类型 | |
与2017年15.5 | C++ 17 | P0521R0型 | 正在弃用共享的u ptr::unique() | [折旧] |
与2017年15.5 | C++ 17 | P0607R0型 | STL的内联变量 | |
与2017年15.5 | C++ 17 | P0618R0型 | 弃用 |
[折旧] |
与2017年15.3 | C++ 20 | P0858R0型 | Constexpr迭代器要求 | [17] |
与2017年15.3 | C++ 17 | … | Boyer Moore搜索() | |
与2017年15.3 | C++ 17 | P0031R0型 | |
|
与2017年15.3 | C++ 17 | P0040R3型 | 扩展内存管理工具 | |
与2017年15.3 | C++ 17 | P0084R2型 | 安放返回类型 | |
与2017年15.3 | C++ 17 | P0152R1型 | 原子::锁总是空闲的吗 | |
与2017年15.3 | C++ 17 | P0154R1型 | 硬件、破坏性干扰、尺寸等。 | |
与2017年15.3 | C++ 17 | P0156R2型 | 作用域锁定 | |
与2017年15.3 | C++ 17 | P0253R1型 | 修复搜索者返回类型 | |
与2017年15.3 | C++ 17 | P0258R2型 | 具有唯一的对象表示 | |
与2017年15.3 | C++ 17 | P0295R0型 | gcd(),lcm() | |
与2017年15.3 | C++ 17 | P0298R3 | 标准::字节 | [字节] |
与2017年15.3 | C++ 17 | P0403R1型 | |
|
与2017年15.3 | C++ 17 | P0418R2型 | 原子比较交换内存顺序要求 | [14] |
与2017年15.3 | C++ 17 | P0435R1型 | 检修普通型 | [14] |
与2017年15.3 | C++ 17 | P0505R0型 | |
|
与2017年15.3 | C++ 17 | P0513R0型 | 中毒杂凑 | [14] |
与2017年15.3 | C++ 17 | P0516R0型 | 将共享复制标记为无例外 | [14] |
与2017年15.3 | C++ 17 | P0517R0型 | 从futureu errc构造futureu error | [14] |
与2017年15.3 | C++ 17 | P0548R1型 | 调整常用类型和持续时间 | [14] |
与2017年15.3 | C++ 17 | P0558R1型 | 解决原子 |
[原子][14] |
与2017年15.3 | C++ 17 | P0599R1型 | noexcept哈希 | [14] |
与2017年15.3 | C++ 17 | P0604R0型 | 调用u结果,is u invocable,is u nothrow u invocable | [折旧] |
VS 2017年 | C++ 17 | … | <算法>样本() | |
VS 2017年 | C++ 17 | … | <任何> | |
VS 2017年 | C++ 17 | … | <可选> | |
VS 2017年 | C++ 17 | … | |
|
VS 2017年 | C++ 17 | … | |
|
VS 2017年 | C++ 17 | P0032R3型 | 变体/任意/可选的同质接口 | |
VS 2017年 | C++ 17 | P0077R2型 | 是可调用的,不是可调用的吗 | |
VS 2017年 | C++ 17 | P0088R3型 | <变体> | |
VS 2017年 | C++ 17 | P0163R0型 | 共享u ptr::弱u类型 | |
VS 2017年 | C++ 17 | P0209R2型 | 从u tuple()生成u | |
VS 2017年 | C++ 17 | P0254R2型 | 集成字符串视图和std::string | |
VS 2017年 | C++ 17 | P0307R2型 | 使可选的更大的值再次相等 | |
VS 2017年 | C++ 17 | P0393R3型 | 使变量更大相等 | |
VS 2017年 | C++ 17 | P0504R0型 | 重访地点/地点类型/地点索引 | |
VS 2017年 | C++ 17 | P0510R0型 | 拒绝Nothing、数组、引用和不完整类型的变体 | |
与2015.3相比 | C++ 17 | P0025R1型 | 夹紧() | |
与2015.3相比 | C++ 17 | P0185R1型 | 是可交换的,不是可交换的吗 | |
与2015.3相比 | C++ 17 | P0272R1型 | 非常量基本字符串::data() | |
与2015.2相比 | C++ 17 | N4387号 | 改进成对和元组 | [14] |
与2015.2相比 | C++ 17 | N4508型 | 共享的u互斥体(未命名) | [14] |
与2015.2相比 | C++ 17 | P0004R1型 | 删除不推荐使用的Iostreams别名 | [雷姆] |
与2015.2相比 | C++ 17 | P0006R0型 | 类型特征的变量模板(是否相同等) | [14] |
与2015.2相比 | C++ 17 | P0007R1型 | 作为常量() | [14] |
与2015.2相比 | C++ 17 | P0013R1型 | 逻辑运算符类型特征(连词等) | [14] |
与2015.2相比 | C++ 17 | P0074R0型 | 所有者减少<> | [14] |
与2015.2相比 | C++ 17 | P0092R1型 | |
[14] |
与2015.2相比 | C++ 17 | P0156R0型 | 可变锁护板 | [14] |
与2015年相比 | C++ 17 | 编号3911 | 无效 | [14] |
与2015年相比 | C++ 17 | N4089型 | 独特的安全转换 | [14] |
与2015年相比 | C++ 17 | N4169号 | 调用() | [14] |
与2015年相比 | C++ 17 | N4190型 | 正在删除autou ptr、randomu shuffle()和旧的 |
[雷姆] |
与2015年相比 | C++ 17 | 4258号 | 无异常清理 | [14] |
与2015年相比 | C++ 17 | 4259号 | 未捕获的异常() | [14] |
与2015年相比 | C++ 17 | 编号4277 | 普通可复制的引用u包装 | [14] |
与2015年相比 | C++ 17 | 编号4279 | 为映射/无序映射插入u或u assign()/尝试u emplace() | [14] |
与2015年相比 | C++ 17 | N4280型 | size(),empty(),data() | [14] |
与2015年相比 | C++ 17 | N4366号 | 精确约束唯一的ptr分配 | [14] |
与2015年相比 | C++ 17 | N4389号 | 布尔常数 | [14] |
与2015年相比 | C++ 17 | P0063R3型 | C11标准库 | [C11][14号] |
与2013年相比 | C++ 17 | N4510型 | 支持向量/列表/转发列表中的不完整类型 | [14] |
与2010年相比 | C++ 20 | P0809R0型 | 比较无序容器 | [14] |
- C++ 20: 在C++ 20之前,我们正在努力完成C++ 17,所以尚未实现C++ 20的特性没有在这些表中列出。在STL中,“17早于20”有一些小的例外。 P0809R0型 “比较无序容器”和 P0858R0型 我们的实现已经实现了“Constexpr迭代器需求”,并且 P0777R1型 “避免不必要的衰退”纯粹是编译器吞吐量的改进。
- 药方: 为了清楚起见,我们省略了一些不适用的文件(实现者不需要做什么,用户也不需要利用这些文件),比如措辞澄清。
- [throw()]: 在/std:c++14 模式下,动态异常规范仍然没有实现,throw()仍然被视为uu declspec(nothrow)的同义词。在C++ 17中,动态异常规范主要通过 P0003R5型 ,留下一个痕迹:throw()已被弃用,并且必须作为noexcept的同义词。在/std:c++17 模式下,MSVC现在通过赋予throw()与noexcept相同的行为来符合标准,即通过终止来执行。编译器选项 /Zc:noexcept