跳到主要内容

JEP 347:启用 C++14 语言功能

概括

允许在 JDK C++ 源代码中使用 C++14 语言功能,并给出有关哪些功能可以在 HotSpot 代码中使用的具体指导。

目标

通过 JDK 15,JDK 中 C++ 代码使用的语言功能已仅限于 C++98/03 语言标准。在 JDK 11 中,代码已更新以支持使用较新版本的 C++ 标准进行构建,尽管它尚未使用任何新功能。这包括能够使用支持 C++11/14 语言功能的各种编译器的最新版本进行构建。

此 JEP 的目的是正式允许 JDK 内的 C++ 源代码更改以利用 C++14 语言功能,并提供有关哪些功能可以在 HotSpot 代码中使用的具体指导。

非目标

此 JEP 不建议对 HotSpot 之外的 JDK 中的 C++ 代码进行任何用法或样式更改。 HotSpot 和非 HotSpot 代码的规则已经不同。例如,C++ 异常在某些非 HotSpot 代码中使用,但在 HotSpot 中构建时选项不允许使用。但是,构建一致性要求将使较新的语言功能可用于 JDK 中的所有 C++ 代码。

描述

构建系统的变化

为了利用 C++14 语言功能,需要进行一些构建时更改,具体情况取决于平台编译器。还需要指定各种平台编译器的最低可接受版本。应明确指定所需的语言标准;更高版本的编译器可能默认为更高版本且可能不兼容的语言标准。

  • Windows:JDK 11 需要 Visual Studio 2017。(早期版本将生成配置时警告,并且可能会或可能不会工作。)对于 Visual Studio 2017,默认 C++ 标准是 C++14。/std:c++14应添加该选项。对旧版本的支持将完全删除。

  • Linux:将-std=gnu++98编译器选项替换为-std=c++14. gcc 的最低支持版本是 5.0。

  • macOS:将-std=gnu++98编译器选项替换为-std=c++14. clang 的最低支持版本是 3.5。

  • AIX/PowerPC:将-std=gnu++98编译器选项替换为-std=c++14并要求使用 xlclang++ 作为编译器。 xlclang++ 支持的最低版本是 16.1。

HotSpot 代码中 C++ 用法的更改

HotSpot 代码中 C++ 使用的现有限制和最佳实践建议基于 C++98/03 语言标准,并在HotSpot 样式指南中进行了描述。

我们将在该文档中添加针对最新语言标准功能的类似限制和指南。它们将通过允许的功能表和另一个排除的功能表来描述。使用允许的功能可能是无条件的,也可能有一些限制或附加指导。禁止在 HotSpot 代码中使用排除的功能。

还有第三类,即未定的功能,HotSpot 开发人员尚未就其达成共识,或者可能根本没有讨论过。也禁止使用这些功能。

但请注意,某些语言功能的使用可能不会立即显而易见,并且可能会意外地使用,因为编译器会接受它们。与往常一样,代码审查过程是应对这种情况的主要防御措施。

对功能分类的拟议更改由HotSpot 组成员粗略共识批准,并由组负责人确定。此类更改必须记录在样式指南的更新中。

C++11 和 C++14 的新功能列表及其描述链接可以在某些编译器和库的在线文档中找到:

根据经验,鼓励允许简化代码编写(尤其是阅读代码)的功能。

HotSpot 很大程度上避免使用 C++ 标准库。其中一些原因可能已经过时(特别是早期版本中遇到的错误),而其他原因可能仍然适用(最小化依赖性)。标准库的分类应该经历与语言特性相同的过程。

HotSpot 的一组初始功能分类如下。

允许

  • constexpr

    • 放宽功能要求constexprn3652
    • 广义常量表达式 ( n2235 )

    宽松constexpr(n3652) 或许是区分 C++14 和 C++11 的关键特征。该constexpr功能将允许消除一些笨拙的宏代码,以支持constexpr函数。此功能也是简化元编程习惯的基础。请参阅mpl11mpl11_2

  • 大小释放 ( n3778 ) — 由于 Visual Studio,语法已在使用。

  • 可变参数模板

    • 可变参数模板 ( n2242 )
    • 扩展可变参数模板模板参数(n2555

    可能只是偶尔直接有用,但是是简化元编程习惯用法的基础,例如mpl11mpl11_2中描述的。

  • 静态断言 ( n1720 ) — 替换 HotSpot STATIC_ASSERT 宏,提供更好的错误消息。

  • decltype

    • 表达式的声明类型 ( n2343 )
    • decltype和调用表达式 ( n3276 )

    重要的元编程工具。需要实现简化的功能模板 SFINAE 实用程序。

  • 直角括号 ( n1757 ) — 消除令人讨厌的语法缺陷。

  • 函数模板的默认模板参数 ( CWG D226 ) — 除了其本身有用之外,还需要实现简化的函数模板 SFINAE 实用程序。

  • 模板别名 ( n2258 ) — 带有模板参数的 Typedef。提供类模板的部分特化语法,而不是使用继承(有时以不适当的方式)。还用作元编程mpl11mpl11_2的简化方法中的元函数。

  • 强类型枚举 ( n2347 ) — 允许显式控制枚举的基础类型,而不是保留其潜在的实现定义(并且在实现之间有所不同)。还允许枚举类的强类型,消除隐式转换。当枚举器确实是一组逻辑值时,建议使用_作用域枚举_。允许使用_无作用域枚举_,但在不使用自动初始化程序功能时应首选普通常量。应始终显式指定_枚举基数_,而不是使其依赖于枚举器值的范围和平台。

  • 委托构造函数 ( n1986 ) — 通过允许专用构造函数链接到更通用的构造函数,消除了一些代码重复和简化。

  • 显式转换运算符 ( n2437 ) — 用于使某些现有转换运算符安全。

  • 标准布局类型 ( n2342 )

  • 默认和删除的功能 ( n2346 )

  • 并发动态初始化和销毁​​ ( n2660 ) — 线程安全的函数局部静态。

  • <type_traits>是一个核心元编程库。它消除了对许多 HotSpot 元编程实用程序的需要,这些实用程序是根据该库的相应部分建模的。

  • final类和虚拟函数的虚拟说明符 ( n2928 )、( n3206 )、 ( n3272 ) — 该final说明符允许虚拟函数调用的去虚拟化。与依赖编译器使用诸如点分析或推测性去虚拟化之类的技术相比,这可以提供更好的性能。虚函数的说明符overrides(也在参考论文中进行了描述)可能会在稍后考虑。

  • 本地和未命名类型作为模板参数 ( n2657 ) — 当使用模板时,允许将使用一次的帮助程序类的本地定义放置在使用点附近,而不是要求在命名空间范围内定义此类帮助程序。

  • nullptrstd::nullptr_t( n2431 )

  • auto变量声明 ( n1984 ) — 仅当它使代码更清晰或更安全时才使用。不要仅仅为了避免编写显式类型带来的不便而使用它,除非该类型本身很难编写。对于局部变量,这可以通过消除明显或不相关的类型信息来使代码更清晰。过度使用会使代码更难理解。

  • 函数返回类型推导 ( n3638 ) — 仅当函数体具有非常少量的return语句且通常相对较少的其他代码时才使用。

  • 表达 SFINAE ( n2634 )

排除

  • 新的字符串和字符文字

    • 新的字符类型(n2249
    • Unicode 字符串文字 ( n2442 )
    • 原始字符串文字 ( n2442 )
    • 通用字符名称文字 ( n2170 )

    HotSpot 不需要任何新的字符和字符串文字类型。

  • 用户定义的文字 ( n2765 ) — 用户定义的文字不应该随意添加,而只能通过建议添加特定的 UDL。

  • 内联命名空间 ( n2535 ) — HotSpot 对命名空间的使用非常有限。

  • using namespace指令。特别是,不要使用using namespace std;来避免需要限定标准库名称。

  • 传播异常 ( n2179 ) — HotSpot 不允许使用异常,因此此功能没有用。

  • thread_local( n2659 ) — 使用 HotSpotTHREAD_LOCAL宏;请参阅JDK-8230877的讨论。

  • <atomic>n2427),(n2752);相反,请使用 HotSpotAtomic类和相关设施。

  • [[deprecated]]属性 ( n3760 ) — 与 HotSpot 代码无关。

其他一些项目的类似列表

风险和假设

可能还有其他带有工具链的平台尚不支持 C++14 语言标准。

某些编译器对某些新功能的支持可能存在错误。