openjdk.ruOpenJDK на русском

JEP 347: Enable C++14 Language Features

Включение возможностей языка C++14

ОтветственныйKim Barrett
ТипInfrastructure
ОбластьImplementation
СтатусClosed / Delivered
Выпуск16
Компонентhotspot / other
Обсуждениеhotspot dash dev at openjdk dot java dot net
РецензентыDavid Holmes, Mikael Vidstedt
ОдобренMikael Vidstedt
Создан2018/07/23 14:30
Обновлён2024/08/14 10:28
Задача8208089

Аннотация

Разрешить использование возможностей языка C++14 в исходном коде JDK на C++ и дать конкретные рекомендации о том, какие из этих возможностей можно использовать в коде HotSpot.

Цели

Вплоть до JDK 15 возможности языка, используемые в коде на C++ в JDK, ограничивались стандартами языка C++98/03. В JDK 11 код был обновлён для поддержки сборки с более новыми версиями стандарта C++, хотя никаких новых возможностей он пока не использует. Это включает возможность сборки последними версиями различных компиляторов, поддерживающих возможности языка C++11/14.

Цель этого JEP — официально разрешить изменения исходного кода на C++ в JDK, использующие возможности языка C++14, и дать конкретные рекомендации о том, какие из этих возможностей можно использовать в коде HotSpot.

Что не является целью

Этот JEP не предлагает никаких изменений в использовании или стиле кода на C++ в JDK вне HotSpot. Правила для кода HotSpot и кода вне HotSpot уже различаются. Например, исключения C++ используются в некотором коде вне HotSpot, но в HotSpot запрещены параметрами сборки. Однако из-за требований к согласованности сборки новые возможности языка станут доступны для использования во всём коде на C++ в JDK.

Описание

Изменения в системе сборки

Чтобы использовать возможности языка C++14, требуются некоторые изменения в сборке, детали которых зависят от компилятора платформы. Также нужно указать минимальные допустимые версии компиляторов для различных платформ. Нужный стандарт языка следует указывать явно: более поздние версии компиляторов могут по умолчанию использовать более поздний и, возможно, несовместимый стандарт языка.

  • Windows: для JDK 11 требуется Visual Studio 2017. (Более ранние версии приведут к предупреждению на этапе configure и могут как работать, так и не работать.) Для 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.

Изменения в использовании C++ в коде HotSpot

Существующие ограничения и рекомендации по лучшим практикам использования C++ в коде HotSpot основаны на стандарте языка C++98/03 и описаны в HotSpot Style Guide.

Мы добавим в этот документ аналогичные ограничения и рекомендации для возможностей более новых стандартов языка. Они будут описаны в виде таблицы разрешённых возможностей и таблицы исключённых возможностей. Использование разрешённых возможностей может быть безусловным или может иметь некоторые ограничения либо дополнительные рекомендации. Использование исключённых возможностей в коде HotSpot запрещено.

Существует третья категория — возможности, по которым решение не принято: по ним разработчики HotSpot не достигли консенсуса или, возможно, вообще их не обсуждали. Использование этих возможностей также запрещено.

Однако обратите внимание, что использование некоторых возможностей языка может быть не сразу заметно, и они всё равно могут случайно попасть в код, поскольку компилятор их примет. Как всегда, основной защитой от этого служит процесс ревью кода.

Предлагаемые изменения категории возможности утверждаются приблизительным консенсусом членов группы HotSpot, который определяет Group Lead. Такие изменения должны быть задокументированы в обновлениях Style Guide.

Списки новых возможностей C++11 и C++14 вместе со ссылками на их описания можно найти в онлайн-документации некоторых компиляторов и библиотек:

Как правило, приветствуется разрешение возможностей, которые упрощают написание и особенно чтение кода.

HotSpot в основном избегал использования стандартной библиотеки C++. Некоторые из причин этого могут быть устаревшими (в частности, ошибки, встречавшиеся в ранних версиях), а другие могут быть по-прежнему актуальны (минимизация зависимостей). Отнесение частей стандартной библиотеки к категориям должно проходить через тот же процесс, что и для возможностей языка.

Ниже приведено начальное распределение возможностей по категориям для HotSpot.

Разрешено

  • constexpr

    • Ослабление требований к функциям constexpr (n3652)
    • Обобщённые константные выражения (n2235)

    Ослабленный constexpr (n3652) — пожалуй, ключевая возможность, отличающая C++14 от C++11. Возможность constexpr позволит устранить часть громоздкого кода на макросах в пользу функций constexpr. Эта возможность также лежит в основе упрощённых идиом метапрограммирования. См. mpl11 и mpl11_2.

  • Освобождение памяти с указанием размера (n3778) — синтаксис уже используется из-за Visual Studio.

  • Шаблоны с переменным числом аргументов

    • Шаблоны с переменным числом аргументов (n2242)
    • Расширение шаблонных параметров шаблона с переменным числом аргументов (n2555)

    Вероятно, напрямую полезно лишь изредка, но служит основой для упрощённых идиом метапрограммирования, например описанных в mpl11 и mpl11_2.

  • Статические утверждения (n1720) — заменяют макрос HotSpot STATIC_ASSERT и дают более понятные сообщения об ошибках.

  • decltype

    • Объявленный тип выражения (n2343)
    • decltype и выражения вызова (n3276)

    Важный инструмент метапрограммирования. Нужен для реализации упрощённой утилиты SFINAE для шаблонов функций.

  • Правые угловые скобки (n1757) — устраняют досадный синтаксический изъян.

  • Аргументы шаблона по умолчанию для шаблонов функций (CWG D226) — помимо того что это полезно само по себе, это нужно для реализации упрощённой утилиты SFINAE для шаблонов функций.

  • Псевдонимы шаблонов (n2258) — typedef с параметрами шаблона. Дают синтаксис для частичных специализаций шаблона класса вместо использования наследования (иногда неуместным образом). Также используются как метафункции в упрощённом подходе к метапрограммированию mpl11 и mpl11_2.

  • Строго типизированные перечисления (n2347) — позволяют явно управлять базовым типом перечисления, а не оставлять его потенциально определяемым реализацией (и различающимся между реализациями). Также позволяют строгую типизацию для enum-классов, устраняя неявные преобразования. Рекомендуется использовать scoped-enums, когда перечислители действительно представляют логический набор значений. Использование unscoped-enums разрешено, хотя, если возможность автоматической инициализации не используется, следует предпочитать обычные константы. enum-base всегда следует указывать явно, а не оставлять его зависящим от диапазона значений перечислителей и от платформы.

  • Делегирующие конструкторы (n1986) — устраняют часть дублирования кода и упрощают код, позволяя специализированным конструкторам вызывать по цепочке более общие конструкторы.

  • Явные операторы преобразования (n2437) — использовать, чтобы сделать некоторые существующие операторы преобразования безопасными.

  • Типы со стандартной компоновкой (n2342)

  • Функции, явно заданные по умолчанию, и удалённые функции (n2346)

  • Динамическая инициализация и уничтожение при конкурентности (n2660) — потокобезопасные локальные статические переменные функций.

  • <type_traits> — базовая библиотека метапрограммирования. Она избавляет от необходимости во многих утилитах метапрограммирования HotSpot, которые были созданы по образцу соответствующих частей этой библиотеки.

  • Виртуальные спецификаторы final для классов и виртуальных функций (n2928), (n3206), (n3272) — спецификатор final позволяет девиртуализировать вызовы виртуальных функций. Это может дать более высокую производительность, чем расчёт на то, что компилятор применит такие техники, как анализ указателей или спекулятивная девиртуализация. Спецификатор overrides для виртуальных функций, который также описан в упомянутых документах, может быть рассмотрен позднее.

  • Локальные и безымянные типы как параметры шаблона (n2657) — позволяют размещать локальное определение одноразовых вспомогательных классов рядом с местом использования, когда это использование — шаблон, вместо того чтобы требовать определять такие вспомогательные классы в области видимости пространства имён.

  • nullptr и std::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) — используйте макрос HotSpot THREAD_LOCAL; см. обсуждение JDK-8230877.

  • <atomic> (n2427), (n2752); вместо этого используйте класс HotSpot Atomic и связанные с ним средства.

  • Атрибут [[deprecated]] (n3760) — неактуален для кода HotSpot.

Аналогичные списки для некоторых других проектов

  • Google C++ Style Guide — сейчас ориентирован на C++11, C++14 использовать не следует

  • C++11 and C++14 use in Chromium — делит возможности на разрешённые, запрещённые и подлежащие обсуждению.

  • llvm Coding Standards — сейчас ориентированы на C++11, C++14 использовать не следует.

  • Using C++ in Mozilla code — требуется поддержка C++14.

Риски и допущения

Могут существовать и другие платформы, наборы инструментов которых пока не поддерживают стандарт языка C++14.

В поддержке некоторых новых возможностей отдельными компиляторами могут быть ошибки.