С++14
Версии языка C++ |
---|
C++14 — это версия стандарта ISO / IEC 14882 для языка программирования C++ . Он задумывался как небольшое расширение C ++11 , включающее в основном исправления ошибок и небольшие улучшения, и был заменен C++17 . О его одобрении было объявлено 18 августа 2014 года. [ 1 ] C++14 был опубликован как ISO/IEC 14882:2014 в декабре 2014 года. [ 2 ]
Поскольку более ранние версии стандарта C++ были заметно запоздалыми, вместо него иногда использовалось имя «C++1y» до его утверждения, аналогично тому, как стандарт C++11 раньше назывался «C++0x» в ожидании его выпуска. до 2010 года (хотя на самом деле он скатился на 2010 год и наконец на 2011 год).
Новые возможности языка
[ редактировать ]Это функции, добавленные в основной язык C++14.
Вывод типа возвращаемого значения функции
[ редактировать ]C++11 позволял лямбда-функциям определять тип возвращаемого значения на основе типа выражения, заданного в операторе return. C++14 предоставляет эту возможность всем функциям. Он также расширяет эти возможности на лямбда-функции, позволяя выводить тип возвращаемого значения для функций, которые не имеют вида return expression;
. [ 3 ]
Чтобы вызвать вывод типа возвращаемого значения, функция должна быть объявлена с помощью auto
в качестве возвращаемого типа, но без завершающего спецификатора возвращаемого типа в C++11:
auto DeduceReturnType(); // Return type to be determined.
Если в реализации функции используется несколько возвращаемых выражений, то все они должны выводить один и тот же тип. [ 4 ]
Функции, которые определяют возвращаемые типы, могут быть объявлены заранее, но их нельзя использовать, пока они не определены. Их определения должны быть доступны единице перевода, которая их использует.
Рекурсию можно использовать с функцией этого типа, но рекурсивный вызов должен произойти хотя бы после одного оператора return в определении функции: [ 4 ]
auto Correct(int i)
{
if (i == 1)
return i; // return type deduced as int
return Correct(i-1)+i; // ok to call it now
}
auto Wrong(int i)
{
if (i != 1)
return Wrong(i-1)+i; // Too soon to call this. No prior return statement.
return i; // return type deduced as int
}
Альтернативный тип вычета при декларировании
[ редактировать ]В C++11 были добавлены два метода вывода типов. auto
был способом создания переменной соответствующего типа на основе заданного выражения. decltype
был способом вычисления типа данного выражения. Однако, decltype
и auto
выводить типы разными способами. В частности, auto
всегда выводит не ссылочный тип, как будто используя std::decay
, пока auto&&
всегда выводит ссылочный тип. Однако, decltype
можно подтолкнуть к выводу ссылочного или нессылочного типа в зависимости от категории значения выражения и природы выводимого выражения: [ 5 ] [ 3 ]
int i;
int&& f();
auto x3a = i; // decltype(x3a) is int
decltype(i) x3d = i; // decltype(x3d) is int
auto x4a = (i); // decltype(x4a) is int
decltype((i)) x4d = (i); // decltype(x4d) is int&
auto x5a = f(); // decltype(x5a) is int
decltype(f()) x5d = f(); // decltype(x5d) is int&&
C++14 добавляет decltype(auto)
синтаксис. Это позволяет auto
декларации об использовании decltype
правила для данного выражения.
The decltype(auto)
синтаксис также можно использовать с выводом типа возвращаемого значения , используя decltype(auto)
синтаксис вместо auto
для вывода типа возвращаемого значения функции. [ 4 ]
Ослабленные ограничения constexpr
[ редактировать ]В C++11 введена концепция функции, объявленной constexpr; функция, которая может быть выполнена во время компиляции. Их возвращаемые значения могут использоваться операциями, требующими постоянных выражений, таких как целочисленный аргумент шаблона. Однако функции constexpr C++11 могут содержать только одно возвращаемое выражение (а также static_assert
s и небольшое количество других деклараций).
C++14 ослабляет эти ограничения. Функции, объявленные Constexpr, теперь могут содержать следующее: [ 3 ]
- Любые декларации, кроме:
static
илиthread_local
переменные.- Объявления переменных без инициализаторов.
- Операторы условного ветвления
if
иswitch
. - Любой оператор цикла, включая диапазон
for
. - Выражения, которые изменяют значение объекта, если время жизни этого объекта началось внутри функции постоянного выражения. Сюда входят звонки на любые не-
const
constexpr
-объявлены нестатические функции-члены.
goto
операторы запрещены в расслабленных функциях, объявленных constexpr, в C++14.
Кроме того, в C++11 указано, что все объявленные нестатические функции-члены constexpr
были также неявно объявлены const
, относительно this
. С тех пор это было удалено; нестатические функции-члены могут быть не- const
. [ 6 ] Однако в соответствии с указанными выше ограничениями не const
constexpr
Функция-член может изменять член класса только в том случае, если время существования этого объекта началось в рамках оценки постоянного выражения.
Переменные шаблоны
[ редактировать ]В предыдущих версиях C++ шаблонизировать можно было только функции, классы или псевдонимы типов. C++14 позволяет создавать шаблонные переменные. Примером, приведенным в предложении, является переменная pi
который можно прочитать, чтобы получить значение числа Пи для различных типов (например, 3
при прочтении как целочисленный тип; максимально близкое значение, возможное с float
, double
или long double
точность при чтении как float
, double
или long double
, соответственно; и т. д.).
К таким объявлениям и определениям применяются обычные правила шаблонов, включая специализацию. [ 7 ] [ 8 ]
template<typename T>
constexpr T pi = T(3.141592653589793238462643383);
// Usual specialization rules apply:
template<>
constexpr const char* pi<const char*> = "pi";
Инициализация совокупного члена
[ редактировать ]В C++11 добавлены инициализаторы членов по умолчанию — выражения, которые будут применяться к членам в области класса, если конструктор не инициализировал сам член. Определение агрегатов было изменено, чтобы явно исключить любой класс с инициализаторами членов; поэтому им не разрешено использовать агрегатную инициализацию.
C++14 ослабляет это ограничение. [ 3 ] позволяющая агрегатную инициализацию таких типов. Если список инициализации в фигурных скобках не предоставляет значения для этого аргумента, об этом позаботится инициализатор элемента. [ 9 ]
Двоичные литералы
[ редактировать ]Числовые литералы в C++14 можно указывать в двоичной форме . [ 3 ] В синтаксисе используются префиксы 0b
или 0B
. Синтаксис также используется в других языках, например Java , C# , Swift , Go , Scala , Ruby , Python , OCaml , а также в качестве неофициального расширения в некоторых компиляторах C, по крайней мере, с 2007 года. [ 10 ]
Разделители цифр
[ редактировать ]В C++14 символ одинарной кавычки может использоваться произвольно в качестве разделителя цифр в числовых литералах, как целочисленных литералах , так и литералах с плавающей запятой. [ 11 ] Это может облегчить читателям анализ больших чисел посредством субитизации .
auto integer_literal = 1'000'000;
auto floating_point_literal = 0.000'015'3;
auto binary_literal = 0b0100'1100'0110;
auto a_dozen_crores = 12'00'00'000;
Общие лямбды
[ редактировать ]В C++11 параметры лямбда-функции необходимо объявлять с конкретными типами. C++14 ослабляет это требование, позволяя объявлять параметры лямбда-функции с помощью auto
указатель типа. [ 7 ]
auto lambda = [](auto x, auto y) {return x + y;};
Касательно auto
вывод типа, общие лямбды следуют правилам вывода аргументов шаблона (которые похожи, но не идентичны во всех отношениях). [ нужны разъяснения ] ). Код выше эквивалентен этому: [ 12 ]
struct
{
template<typename T, typename U>
auto operator()(T x, U y) const {return x + y;}
} lambda{};
Общие лямбды — это, по сути, шаблонные лямбды-функторы.
Лямбда-выражения захвата
[ редактировать ]Лямбда-функции C++11 захватывают переменные, объявленные во внешней области, путем копирования значения или по ссылке. Это означает, что члены-значения лямбды не могут быть типами, предназначенными только для перемещения. [ 13 ] C++14 позволяет инициализировать захваченные члены произвольными выражениями. Это позволяет как захватывать путем перемещения значения, так и объявлять произвольные члены лямбды без наличия переменной с соответствующим именем во внешней области видимости. [ 7 ]
Это делается с помощью выражения инициализатора:
auto lambda = [value = 1] {return value;};
Лямбда-функция lambda
возвращает 1, вот что value
был инициализирован с помощью. Объявленный захват выводит тип из выражения инициализатора, как если бы auto
.
Это можно использовать для захвата движением с помощью стандартного std::move
функция:
std::unique_ptr<int> ptr(new int(10));
auto lambda = [value = std::move(ptr)] {return *value;};
Атрибут [[deprecated]]
[ редактировать ] The deprecated
Атрибут позволяет пометить объект как устаревший , что делает его использование по-прежнему законным, но предупреждает пользователей о том, что использование не рекомендуется, и может привести к выводу предупреждающего сообщения во время компиляции. Необязательный строковый литерал может выступать в качестве аргумента deprecated
, чтобы объяснить причину прекращения поддержки и предложить замену.
[[deprecated]] int f();
[[deprecated("g() is thread-unsafe. Use h() instead")]]
void g( int& x );
void h( int& x );
void test()
{
int a = f(); // warning: 'f' is deprecated
g(a); // warning: 'g' is deprecated: g() is thread-unsafe. Use h() instead
}
Новые возможности стандартной библиотеки
[ редактировать ]Общие мьютексы и блокировки
[ редактировать ]В C++14 добавлены общий временной мьютекс и сопутствующий тип общей блокировки. [ 14 ] [ 15 ]
Гетерогенный поиск в ассоциативных контейнерах
[ редактировать ]Стандартная библиотека C++ определяет четыре ассоциативных класса контейнеров. Эти классы позволяют пользователю искать значение на основе значения этого типа. Контейнеры карт позволяют пользователю указывать ключ и значение, при этом поиск выполняется по ключу и возвращает значение. Однако поиск всегда выполняется по конкретному типу ключа, будь то ключ, как в картах, или само значение, как в наборах.
C++14 позволяет выполнять поиск по произвольному типу, если оператор сравнения может сравнить этот тип с фактическим типом ключа. [ 16 ] Это позволит получить карту из std::string
к некоторому значению для сравнения с const char*
или любой другой тип, для которого operator<
возможна перегрузка. Это также полезно для индексации составных объектов в std::set
по значению одного члена, не заставляя пользователя find
для создания фиктивного объекта (например, создания целого struct Person
найти человека по имени).
Чтобы сохранить обратную совместимость, гетерогенный поиск разрешен только в том случае, если это разрешено компаратором, предоставленным ассоциативному контейнеру. Классы стандартной библиотеки std::less<>
и std::greater<>
расширены, чтобы обеспечить гетерогенный поиск. [ 17 ]
Стандартные пользовательские литералы
[ редактировать ]В C++11 определен синтаксис определяемых пользователем литеральных суффиксов, но стандартная библиотека не использовала ни один из них. В C++14 добавлены следующие стандартные литералы: [ 16 ]
- «s», для создания различных
std::basic_string
типы. - «ч», «мин», «с», «мс», «нас», «нс», для создания соответствующего
std::chrono::duration
временные интервалы. - "if", "i", "il", для создания соответствующего
std::complex<float>
,std::complex<double>
иstd::complex<long double>
мнимые числа.
auto str = "hello world"s; // auto deduces string
auto dur = 60s; // auto deduces chrono::seconds
auto z = 1i; // auto deduces complex<double>
Два литерала «s» не конфликтуют, так как строковый литерал работает только со строковыми литералами , а второй — только с числами. [ 18 ]
Адресация кортежей по типу
[ редактировать ]The std::tuple
type, представленный в C++11, позволяет индексировать совокупность типизированных значений с помощью целого числа, константы времени компиляции. C++14 расширяет эту возможность, позволяя осуществлять выборку из кортежа по типу, а не по индексу. [ 16 ] Если кортеж содержит более одного элемента данного типа, возникает ошибка времени компиляции: [ 19 ]
tuple<string, string, int> t("foo", "bar", 7);
int i = get<int>(t); // i == 7
int j = get<2>(t); // Same as before: j == 7
string s = get<string>(t); // Compile-time error due to ambiguity
Меньшие возможности библиотеки
[ редактировать ]std::make_unique
можно использовать как std::make_shared
для std::unique_ptr
объекты. [ 7 ]
std::integral_constant
получил operator()
перегрузка, чтобы вернуть постоянное значение. [ 16 ]
Шаблон класса std::integer_sequence
и соответствующие шаблоны псевдонимов были добавлены для представления целочисленных последовательностей времени компиляции, таких как индексы элементов в пакете параметров. [ 20 ]
Глобальный std::begin
/ std::end
функции были дополнены std::cbegin
/ std::cend
функции, которые возвращают постоянные итераторы, и std::rbegin
/ std::rend
и std::crbegin
/ std::crend
которые возвращают обратные итераторы.
The std::exchange
Шаблон функции присваивает новое значение переменной и возвращает старое значение. [ 21 ]
Новые перегрузки std::equal
, std::mismatch
, и std::is_permutation
возьмите пару итераторов для второго диапазона, чтобы вызывающему объекту не нужно было отдельно проверять, имеют ли два диапазона одинаковую длину. [ 22 ]
The std::is_final
Типовая черта определяет, отмечен ли класс final
.
The std::quoted
Манипулятор потокового ввода-вывода позволяет вставлять и извлекать строки со встроенными пробелами, помещая разделители (по умолчанию двойные кавычки) на выходе и удаляя их на входе, а также экранируя любые встроенные разделители. [ 23 ]
Поддержка компилятора
[ редактировать ]Clang завершил поддержку C++14 в версии 3.4, хотя и под стандартным именем c++1y, и сделал C++14 стандартом C++ по умолчанию в Clang 6. [ 24 ] GCC завершил поддержку C++14 в GCC 5 и сделал C++14 стандартом C++ по умолчанию в GCC 6. [ 25 ] Microsoft Visual Studio 2017 реализовала «почти все» функции C++14. [ 26 ]
Ссылки
[ редактировать ]- ^ Саттер, Херб (18 августа 2014 г.), У нас есть C++14! , получено 18 августа 2014 г.
- ^ «ИСО/МЭК 14882:2014» . ИСО .
- ^ Перейти обратно: а б с д и Вонг, Майкл (30 апреля 2013 г.). «Взгляд с совещания по стандарту C++, апрель 2013 г., часть 1» . Кафе C/C++ . Проверено 27 января 2016 г.
- ^ Перейти обратно: а б с Меррилл, Джейсон (17 апреля 2013 г.). «N3638 Вычисление типа возвращаемого значения для обычных функций (Редакция 5)» . Проверено 14 июня 2013 г.
- ^ «Страница 10 из: Объяснение C++ auto и decltype» .
- ^ Смит, Ричард (18 апреля 2013 г.). «N3652 Ослабление ограничений на функции constexpr» .
- ^ Перейти обратно: а б с д Саттер, Херб (20 апреля 2013 г.). «Отчет о поездке: встреча ISO C++ весной 2013 г.» . isocpp.org . Проверено 14 июня 2013 г.
- ^ Дос Рейс, Габриэль (19 апреля 2013 г.). «Шаблоны переменных N3651 (версия 1)» (PDF) .
- ^ Вандевурде, Дэвид; Вотилайнен, Вилле (17 апреля 2013 г.). «Инициализаторы и агрегаты элементов N3653» .
- ^ «23479 — реализация двоичных констант с префиксом «0b» .
- ^ Кроул, Лоуренс; Смит, Ричард; Снайдер, Джефф; Вандевурде, Давид (25 сентября 2013 г.). «N3781 Одинарные кавычки как разделитель цифр» (PDF) .
- ^ Вали, Фейсал; Саттер, Херб; Абрахамс, Дэйв (19 апреля 2013 г.). «Общие (полиморфные) лямбда-выражения N3649 (редакция 3)» .
- ^ «Захват перемещения в Lambda» . Переполнение стека .
- ^ Вонг, Майкл (30 апреля 2013 г.). «Взгляд с совещания по стандарту C++, апрель 2013 г., часть 3» . Кафе C/C++ . Проверено 14 июня 2013 г.
- ^ Хиннант, Ховард; Воллманн, Детлеф; Бём, Ганс (19 апреля 2013 г.). «N3659 Совместная блокировка в C++ (версия 2)» .
- ^ Перейти обратно: а б с д Вонг, Майкл (26 апреля 2013 г.). «Взгляд с совещания по стандарту C++, апрель 2013 г., часть 2» . Кафе C/C++ . Проверено 14 июня 2013 г.
- ^ «N3657 Добавление поиска гетерогенного сравнения в ассоциативные контейнеры (версия 4)» . 19 марта 2013 г.
- ^ Соммерлад, Питер (18 апреля 2013 г.). «Определенные пользователем литералы N3642 для типов стандартных библиотек (часть 1 — версия 4)» (PDF) .
- ^ Спертус, Майк (19 апреля 2013 г.). «Формулировка N3670 для адресации кортежей по типу: редакция 2» .
- ^ Уэйкли, Джонатан (18 апреля 2013 г.). «N3658 Целочисленные последовательности времени компиляции» . Проверено 5 января 2016 г.
- ^ Ясскин, Джеффри (19 апреля 2013 г.). «Вспомогательная функция N3668 Exchange(), версия 3» . Проверено 5 января 2016 г.
- ^ Спертус, Майк; Палл, Аттила (19 апреля 2013 г.). «N3671 Повышение надежности немодифицирующих операций с последовательностями: Редакция 2» . Проверено 5 января 2016 г.
- ^ Дауэс, Беман (19 апреля 2013 г.). «Предложение библиотеки строк в кавычках N3654 (редакция 2)» . Проверено 5 января 2016 г.
- ^ «Поддержка C++ в Clang» . Проверено 28 мая 2016 г.
- ^ «Поддержка стандартов C++ в GCC» . Проверено 28 мая 2016 г.
- ^ «Соответствие стандартам C++ от Microsoft» . 7 марта 2017 года . Проверено 7 марта 2017 г.
Внешние ссылки
[ редактировать ]- C++14: что нужно знать. Обзор возможностей Dr. Dobb's , 16 сентября 2014 г.