C ++ 14 - C++14 - Wikipedia

C ++ 14 это версия Стандарт ISO / IEC 14882 для языка программирования C ++. Он задуман как небольшой расширение над C ++ 11, содержащий в основном исправления ошибок и небольшие улучшения. Об одобрении было объявлено 18 августа 2014 года.[1] C ++ 14 был выпущен 15 декабря 2014 года.[2]

Поскольку более ранние версии стандарта C ++ были заметно запоздалыми, название «C ++ 1y» иногда использовалось до его утверждения, аналогично тому, как стандарт C ++ 11 раньше назывался «C ++ 0x» в ожидании его выпуска. до 2010 года (хотя на самом деле он переместился в 2010 и, наконец, в 2011).

Новые языковые функции

Это функции, добавленные к основному языку C ++ 14.

Выведение типа возвращаемого значения

C ++ 11 разрешен лямбда-функции чтобы вывести тип возвращаемого значения на основе типа выражения, заданного в операторе возврата. C ++ 14 предоставляет эту возможность всем функциям. Он также расширяет эти возможности до лямбда-функций, позволяя выводить тип возвращаемого значения для функций, которые не имеют формы возвращаемое выражение;.[3]

Чтобы вызвать вывод типа возвращаемого значения, функция должна быть объявлена ​​с авто как возвращаемый тип, но без конечного спецификатора возвращаемого типа в C ++ 11:

авто DeduceReturnType();   // Тип возвращаемого значения подлежит определению.

Если в реализации функции используется несколько возвращаемых выражений, все они должны выводить один и тот же тип.[4]

Функции, которые выводят свои возвращаемые типы, могут быть объявлены вперед, но их нельзя использовать, пока они не будут определены. Их определения должны быть доступны для единицы перевода, которая их использует.

Рекурсия может использоваться с функцией этого типа, но рекурсивный вызов должен происходить после хотя бы одного оператора возврата в определении функции:[4]

авто Правильный(int я){  если (я == 1)    возвращаться я;             // возвращаемый тип, выводимый как int  возвращаться Правильный(я-1)+я;  // нормально называть это сейчас}авто Неправильный(int я){  если (я != 1)    возвращаться Неправильный(я-1)+я;  // Слишком рано называть это. Нет предварительного заявления о возврате.  возвращаться я;               // возвращаемый тип, выводимый как int}

Вычет альтернативного типа при объявлении[5]

В C ++ 11 добавлены два метода вывода типов. авто был способом создать переменную соответствующего типа на основе заданного выражения. decltype был способом вычислить тип данного выражения. Тем не мение, decltype и авто выводить типы по-разному. Особенно, авто всегда выводит не ссылочный тип, как будто используя std :: распад, пока авто&& всегда выводит ссылочный тип. Тем не мение, decltype можно подтолкнуть к выведению ссылочного или не ссылочного типа на основе категории значения выражения и природы выражения, которое оно выводит:[3]

int   я;int&& ж();авто          x3a = я;     // decltype (x3a) имеет значение intdecltype(я)   x3d = я;     // decltype (x3d) - это intавто          x4a = (я);   // decltype (x4a) - это intdecltype((я)) x4d = (я);   // decltype (x4d) - это int &авто          x5a = ж();   // decltype (x5a) имеет значение intdecltype(ж()) x5d = ж();   // decltype (x5d) - это int &&

C ++ 14 добавляет decltype (авто) синтаксис. Это позволяет авто декларации об использовании decltype правила для данного выражения.

В decltype (авто) синтаксис также можно использовать с вычет типа возврата, используя decltype (авто) синтаксис вместо авто для вывода типа возвращаемого значения функции.[4]

Ослабленные ограничения constexpr

C ++ 11 представил концепцию функции, объявленной constexpr; функция, которая может быть выполнена во время компиляции. Их возвращаемые значения могут использоваться операциями, требующими постоянных выражений, таких как целочисленный аргумент шаблона. Однако функции constexpr C ++ 11 могут содержать только одно возвращаемое выражение (а также static_asserts и небольшое количество других объявлений).

C ++ 14 ослабляет эти ограничения. Функции, объявленные Constexpr, теперь могут содержать следующее:[3]

  • Любые декларации, кроме:
    • статический или же thread_local переменные.
    • Объявления переменных без инициализаторов.
  • Операторы условного ветвления если и выключатель.
  • Любой оператор цикла, в том числе на основе диапазона за.
  • Выражения, которые изменяют значение объекта, если время жизни этого объекта началось в функции константного выражения. Это включает в себя звонки на любые не-const constexpr-объявленные нестатические функции-члены.

идти к Операторы запрещены в C ++ 14 расслабленных функциях, объявленных constexpr.

Кроме того, в C ++ 11 указано, что все объявленные нестатические функции-члены constexpr также были неявно объявлены const, относительно это. С тех пор это было удалено; нестатические функции-члены могут быть не-const.[6] Однако, согласно указанным выше ограничениям, неconst constexpr функция-член может изменять член класса только в том случае, если время существования этого объекта началось в пределах вычисления константного выражения.

Шаблоны переменных

В предыдущих версиях C ++ можно было использовать только функции, классы или псевдонимы типов. C ++ 14 позволяет создавать переменные по шаблону. В предложении приведен пример переменной число Пи которые можно прочитать, чтобы получить значение число Пи для различных типов (например, 3 при чтении как цельный тип; ближайшее возможное значение с плавать, двойной или же длинный двойной точность при чтении как плавать, двойной или же длинный двойной, соответственно; так далее.).

К таким объявлениям и определениям применяются обычные правила шаблонов, включая специализацию.[7][8]

шаблон<typename Т>constexpr Т число Пи = Т(3.141592653589793238462643383);// Применяются обычные правила специализации:шаблон<>constexpr const char* число Пи<const char*> = "число Пи";

Инициализация совокупного члена

C ++ 11 добавлены инициализаторы членов, выражения, которые будут применяться к членам в области класса, если конструктор не инициализировал сам член. Определение агрегатов было изменено, чтобы явно исключить любой класс с инициализаторами членов; поэтому им не разрешено использовать агрегатную инициализацию.

C ++ 14 снимает это ограничение,[3] возможность агрегированной инициализации для таких типов. Если список инициализации в фигурных скобках не предоставляет значение для этого аргумента, инициализатор элемента позаботится об этом.[9]

Двоичные литералы

Числовые литералы в C ++ 14 могут быть указаны в двоичная форма.[3] В синтаксисе используются префиксы 0b или же 0B. Синтаксис также используется в других языках, например. Ява, C #, Быстрый, Идти, Scala, Рубин, Python, OCaml, и как неофициальное расширение в некоторых компиляторах C по крайней мере с 2007 года.[10]

Разделители цифр

В C ++ 14 символ одинарной кавычки может использоваться произвольно как разделитель цифр в числовых литералах оба целочисленные литералы и литералы с плавающей запятой.[11] Это может упростить для читателей анализ больших чисел через субитизирующий.

авто integer_literal = 1'000'000;
авто Floating_point_literal = 0.000'015'3;
авто binary_literal = 0b0100'1100'0110;
авто дюжина_крор = 12'00'00'000;
авто глупый_пример = 1'0'0'000'00;

Общие лямбды

В C ++ 11 лямбда-функция параметры необходимо объявлять с конкретными типами. C ++ 14 ослабляет это требование, позволяя объявлять параметры лямбда-функции с авто спецификатор типа.[7]

авто лямбда = [](авто Икс, авто у) {возвращаться Икс + у;};

Касательно авто определение типа, общие лямбды следуют правилам вывода аргументов шаблона (которые похожи, но не идентичны во всех отношениях[требуется разъяснение ]). Приведенный выше код эквивалентен этому:[12]

структура{  шаблон<typename Т, typename U>    авто оператор()(Т Икс, U у) const {возвращаться Икс + у;}} лямбда{};

Общие лямбды - это, по сути, шаблонные лямбды-функторы.

Лямбда-выражения

Лямбда-функции C ++ 11 захватывают переменные, объявленные во внешней области видимости, путем копирования значения или по ссылке. Это означает, что члены-значения лямбды не могут быть типами, предназначенными только для перемещения.[13] C ++ 14 позволяет инициализировать захваченные члены произвольными выражениями. Это позволяет как захват с перемещением значения, так и объявление произвольных членов лямбда-выражения без наличия соответствующей именованной переменной во внешней области видимости.[7]

Это делается с помощью выражения инициализатора:

авто лямбда = [ценить = 1] {возвращаться ценить;};

Лямбда-функция лямбда возвращает 1, что и есть ценить был инициализирован с помощью. Объявленный захват выводит тип из выражения инициализатора, как если бы авто.

Это можно использовать для захвата на ходу с помощью стандартного std :: move функция:

стандартное::unique_ptr<int> ptr(новый int(10));авто лямбда = [ценить = стандартное::двигаться(ptr)] {возвращаться *ценить;};

Атрибут [[не рекомендуется]]

В устарел атрибут позволяет пометить объект устарел, что делает его использование легальным, но предупреждает пользователей о том, что использование не рекомендуется, и может привести к тому, что во время компиляции будет напечатано предупреждающее сообщение. Необязательный строковый литерал может выступать в качестве аргумента устарел, чтобы объяснить причину прекращения поддержки и / или предложить замену.

[[устарел]] int ж();[[устарел("g () небезопасен для потоков. Вместо этого используйте h ()")]]пустота грамм( int& Икс );пустота час( int& Икс );пустота тест(){  int а = ж(); // предупреждение: 'f' устарела  грамм(а); // предупреждение: 'g' устарела: g () небезопасна для потоков. Вместо этого используйте h ()}

Новые возможности стандартной библиотеки

Общие мьютексы и блокировка

C ++ 14 добавляет общий синхронизированный мьютекс и сопутствующий общий тип блокировки.[14][15]

Гетерогенный поиск в ассоциативных контейнерах

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

C ++ 14 позволяет выполнять поиск с помощью произвольного типа, если оператор сравнения может сравнивать этот тип с фактическим типом ключа.[16] Это позволит карту из std :: string какое-то значение для сравнения с const char * или любой другой тип, для которого оператор < имеется перегрузка. Это также полезно для индексации составных объектов в std :: set по значению одного члена, не заставляя пользователя найти для создания фиктивного объекта (например, создание всего struct Person найти человека по имени).

Чтобы сохранить обратную совместимость, гетерогенный поиск разрешен только тогда, когда компаратор, присвоенный ассоциативному контейнеру, позволяет это. Классы стандартной библиотеки std :: less <> и std :: больше <> расширены, чтобы разрешить гетерогенный поиск.[17]

Стандартные определяемые пользователем литералы

C ++ 11 определил синтаксис для определяемых пользователем буквальных суффиксов, но стандартная библиотека не использовала ни один из них. C ++ 14 добавляет следующие стандартные литералы:[16]

  • "s", для создания различных std :: basic_string типы.
  • «h», «min», «s», «ms», «us», «ns» для создания соответствующих std :: chrono :: duration временные интервалы.
  • «if», «i», «il», для создания соответствующих std :: complex <плавающий>, std :: complex <двойной> и std :: complex <длинный двойной> мнимые числа.
авто ул = "Привет, мир"s; // автоматически выводит строкуавто dur = 60s;            // автоматически выводит хроно :: секундыавто z   = 1я;             // автоматически выводит сложный 

Два литерала "s" не взаимодействуют, так как строка один работает только с строковые литералы, а секундомер действует только на числа.[18]

Адресация кортежей через тип

В std :: tuple type, представленный в C ++ 11, позволяет индексировать совокупность типизированных значений с помощью целого числа константы времени компиляции. C ++ 14 расширяет это, чтобы разрешить выборку из кортежа по типу, а не по индексу.[16] Если в кортеже более одного элемента типа, возникает ошибка времени компиляции:[19]

кортеж<нить, нить, int> т("фу", "бар", 7);int я = получать<int>(т);        // я == 7int j = получать<2>(т);          // То же, что и раньше: j == 7нить s = получать<нить>(т);  // Ошибка времени компиляции из-за неоднозначности

Меньшие возможности библиотеки

std :: make_unique можно использовать как std :: make_shared за std :: unique_ptr объекты.[7]

std :: integration_constant получил оператор () перегрузка, чтобы вернуть постоянное значение.[16]

Шаблон класса std :: integer_sequence и связанные шаблоны псевдонимов были добавлены для представления целочисленных последовательностей времени компиляции, таких как индексы элементов в пакете параметров.[20]

Глобальный std :: begin/std :: end функции были дополнены std :: cbegin/std :: cend функции, которые возвращают постоянные итераторы, и std :: rbegin/std :: rend и std :: crbegin/std :: crend которые возвращают обратные итераторы.

В std :: exchange шаблон функции присваивает переменной новое значение и возвращает старое значение.[21]

Новые перегрузки std :: equal, std :: mismatch, и std :: is_permutation возьмите пару итераторов для второго диапазона, чтобы вызывающей стороне не нужно было отдельно проверять, что два диапазона имеют одинаковую длину.[22]

В std :: is_final свойство type определяет, отмечен ли класс окончательный.

В std :: quoted Манипулятор потокового ввода-вывода позволяет вставлять и извлекать строки со встроенными пробелами, помещая разделители (по умолчанию в двойные кавычки) на выходе и удаляя их на входе, а также избегая любых встроенных разделителей.[23]

Поддержка компилятора

Лязг завершил поддержку 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]

Рекомендации

  1. ^ Саттер, Херб (18 августа 2014 г.), У нас есть C ++ 14!, получено 2014-08-18
  2. ^ «Поиск ISO / IEC». ISO.
  3. ^ а б c d е Вонг, Майкл (30 апреля 2013 г.). «Взгляд со встречи по стандарту C ++, апрель 2013 г., часть 1». C / C ++ Кафе. Получено 27 января 2016.
  4. ^ а б c Меррилл, Джейсон (17 апреля 2013 г.). «N3638 Вычет типа возврата для обычных функций (Редакция 5)». Получено 14 июн 2013.
  5. ^ http://thbecker.net/articles/auto_and_decltype/section_10.html
  6. ^ Смит, Ричард (18 апреля 2013 г.). "N3652 Ослабление ограничений на функции constexpr".
  7. ^ а б c d Саттер, Херб (20 апреля 2013 г.). «Отчет о поездке: встреча ISO C ++ Spring 2013». isocpp.org. Получено 14 июн 2013.
  8. ^ Дос Рейс, Габриэль (19 апреля 2013 г.). «Шаблоны переменных N3651 (Версия 1)» (PDF).
  9. ^ Вандевурд, Дэвид; Воутилайнен, Вилле (17 апреля 2013 г.). «Инициализаторы и агрегаты членов N3653».
  10. ^ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=23479#c29
  11. ^ Краул, Лоуренс; Смит, Ричард; Снайдер, Джефф; Вандевурде, Дэвид (25 сентября 2013 г.). «Одинарные кавычки N3781 в качестве разделителя цифр» (PDF).
  12. ^ Вали, Фейсал; Саттер, Херб; Абрахамс, Дэйв (19 апреля 2013 г.). «N3649 Generic (Polymorphic) Lambda Expressions (Revision 3)».
  13. ^ «Переместить захват в лямбде». Переполнение стека.
  14. ^ Вонг, Майкл (30 апреля 2013 г.). «Взгляд со встречи по стандарту C ++, апрель 2013 г., часть 3». C / C ++ Кафе. Получено 14 июн 2013.
  15. ^ Хиннант, Ховард; Воллманн, Детлеф; Бем, Ганс (19 апреля 2013 г.). «Совместная блокировка N3659 в C ++ (Версия 2)».
  16. ^ а б c d Вонг, Майкл (26 апреля 2013 г.). «Взгляд со встречи по стандарту C ++, апрель 2013 г., часть 2». C / C ++ Кафе. Получено 14 июн 2013.
  17. ^ "N3657 Добавление гетерогенного сравнительного поиска в ассоциативные контейнеры (версия 4)". 19 марта 2013 г.
  18. ^ Соммерлад, Питер (18 апреля 2013 г.). «N3642 Пользовательские литералы для стандартных библиотечных типов (часть 1 - версия 4)» (PDF).
  19. ^ Спертус, Майк (19 апреля 2013 г.). «Формулировка N3670 для адресации кортежей по типу: редакция 2».
  20. ^ Уэйкли, Джонатан (18 апреля 2013 г.). "N3658 Целочисленные последовательности времени компиляции". Получено 5 января 2016.
  21. ^ Яскин, Джеффри (19 апреля 2013 г.). «Утилита N3668 exchange (), редакция 3». Получено 5 января 2016.
  22. ^ Спертус, Майк; Полл, Аттила (19 апреля 2013 г.). «N3671 Повышение надежности операций с неизменяемыми последовательностями: версия 2». Получено 5 января 2016.
  23. ^ Дауэс, Беман (19 апреля 2013 г.). "Предложение библиотеки цитируемых строк N3654 (редакция 2)". Получено 5 января 2016.
  24. ^ «Поддержка C ++ в Clang». Получено 28 мая 2016.
  25. ^ «Поддержка стандартов C ++ в GCC». Получено 28 мая 2016.
  26. ^ «Соответствие стандартам C ++ от Microsoft». Получено 7 марта 2017.

внешняя ссылка