C++17 (C++17)
C++17 (также известный как C++1z) — это название версии стандарта C++ ISO/IEC. Спецификации для C++17 были опубликованы в декабре 2017 года[1][2].
Значение константы __cplusplus
стало 201703L
, это используется для условной компиляции.
Удалены или запрещены
[править | править код]Удалены триграфы
[править | править код]Триграфы использовались для машин с нестандартной кодировкой и/или ограниченной клавиатурой: так, в немецком ASCII вместо скобок [\]{|}~
умляуты ÄÖÜäöüß
. Ещё в конце 80-х, с распространением 8-битных кодировок, дешёвых резиномембранных клавиатур и качественно локализованных компьютеров, триграфы фактически потеряли смысл, и тридцать лет спустя были закономерно исключены[3][4].
// Will the next line be executed????????????????/
a++; /* с триграфами эта строка закомментирована — триграф ??/ эквивалентен \ */
Удалено ключевое слово register
[править | править код]Язык Си был «переносимым ассемблером»: он позволял делать быстрые программы, компилирующиеся на разных компьютерах, к тому же использовал ассемблерные утилиты (компоновщик, библиотекарь). Понятия вроде «заголовочный файл» и «единица трансляции» — отголоски тех времён.
Слово register
изначально связано с ручной оптимизацией программы. Современные компиляторы «под капотом» делают огромное количество оптимизаций, и подобное ручное управление представляется излишним. Ещё в Си++11 слово объявили нежелательным. Слово всё ещё остаётся зарезервированным, и его могут когда-нибудь задействовать с другой целью — как в Си++11 auto
[5].
Удалена операция ++ для bool
[править | править код]Операция явно небезопасна и запрещена ещё в Си++98[6]. Операция --
отсутствует и так.
Удалены заявленные исключения
[править | править код]Заявленные исключения void f() throw(A, B, C);
, имеющиеся, например, в Java, приносят больше вреда, чем пользы. Запрещены в Си++11, удалены в Си++17. Остался throw()
как синоним для noexcept(true)
[7].
Удалены типы и функции, получившие замену (и ставшие запрещёнными) в Си++11
[править | править код]В их числе std::auto_ptr
, std::random_shuffle
и старые функциональные адаптеры[8][9].
Вместо них используются unique_ptr
, shuffle
и новые функциональные шаблоны, основанные на function
/bind
. Заявляется, что любой код на auto_ptr
может быть механически преобразован в unique_ptr
, с простым добавлением std::move
там, где идёт передача владения.
Также удалены отдельные части iostream
, запрещённые ещё в Си++98[10].
Удалены конструкторы для std::function, принимавшие аллокатор
[править | править код]Всего пять перегрузок, включая эту
template< class Alloc >
function( std::allocator_arg_t, const Alloc& alloc ) noexcept;
Из-за непонятной семантики и сложностей реализации их удалили без предварительного запрета[11].
Запрещены крайне редкие возможности стандартной библиотеки
[править | править код]Запрещено несколько редких возможностей стандартной библиотеки:[12][13][14]
allocator<void>
— оказался невостребованным;- часть функций
allocator
— дублируется шаблономallocator_traits
; raw_storage_iterator
— не вызывает конструкторов и потому ограничен по применению;get_temporary_buffer
— имеет неочевидные подводные камни;is_literal_type
— бесполезен для обобщённого кода, но оставлен, пока в Си++ существует понятие «литеральный тип»;iterator
— проще писать итераторы с нуля, чем основываться на нём;codecvt
— на поверку работал очень плохо, комитет призвал пользоваться специализированными библиотеками;shared_ptr::unique()
— из-за ненадёжности в многопоточной среде.
Полностью удалить обещают в Си++20.
Запреты, связанные с новыми функциями Си++17
[править | править код]result_of
→invoke_result
— более простой синтаксис, основанный на выведении типов Си++11[15];bool uncaught_exception()
→int uncaught_exceptions()
— в обработке одного исключения система может выбросить другое (например, пользователь выдернул флэшку и «посыпались» ошибки ввода-вывода), так что могут «висеть» необработанными и несколько исключений. Проверить, сколько их было в конструкторе и сколько стало в деструкторе — более надёжный и «бесплатный» с точки зрения имеющихся библиотек метод определения, выбрасывать исключение из деструктора или нельзя[16][17][18].
Удалены заголовки библиотеки Си
[править | править код]С переходом на Си11 удалены заголовочные файлы <ccomplex>
, <cstdalign>
, <cstdbool>
, <ctgmath>
. Файл <ciso646>
не запрещён[19].
auto x{};
больше не создаёт initializer_list
[править | править код]Добавленный в Си++11 универсальный инициализатор int x{};
позволяет одним синтаксисом создать объект, структуру, массив. При этом, если есть возможность подставить initializer_list
, подставляет. В Си++17 уточнено: если вместо типа стоит auto
, пользователь хочет создать один объект и никаких initializer_list не нужно.
При этом auto x = {1, 2, 3};
продолжает создавать: с одной стороны, для совместимости с for (auto x : {1, 2, 3})
, с другой — для одного объекта есть auto x = 1;
[20][9].
auto x1 = { 3 }; // std::initializer_list<int>
auto x2 { 1, 2 }; // теперь ошибка
auto x3 { 3 }; // int
Глобальные изменения
[править | править код]Спецификация исключений — теперь часть системы типов
[править | править код]Функции void f() noexcept(true);
и void f() noexcept(false);
— теперь функции с разными типами (но не могут составлять перегруженный набор). Это позволит API требовать callback’и, которые не выбрасывают исключений, а также оптимизировать код под отсутствие таковых[21].
New с чрезмерным выравниванием
[править | править код]В Си++11 появилась возможность создавать структуры данных, чьё выравнивание больше, чем теоретическое. Эта возможность была подхвачена операцией new[22].
class alignas(16) float4 {
float f[4];
};
float4 *p = new float4[1000];
Появилась перегрузка операции new с дополнительным параметром, чтобы корректно разместить в памяти чрезмерно выравненный объект.
Обязательное избавление от копирования
[править | править код]Изменён смысл понятия prvalue: теперь это всего лишь инициализация.
В коде SomeType a = 10;
хоть всё ещё требуется и конструктор, и операция =, гарантированно будет вызван только конструктор.
Это значит, что функции могут возвращать типы, которые нельзя копировать и перемещать.
Более строгий порядок вычисления
[править | править код]Теперь операции a.b
, a->b
, a->*b
, a(b1, b2, b3)
, b += a
(и аналоги для других операций), a[b]
, a << b
и a >> b
вычисляются в порядке a → b, чтобы держать под контролем побочные эффекты[23].
Если их вызвать как функции (например, operator += (a, b)
), порядок остаётся неопределённым.
Расширили понятие «константа в шаблоне»
[править | править код]Существуют шаблоны, принимающие константу.
template <int N> struct Array
{
int a[N];
};
Что может быть константой N, и что не может — объявлено от противного. Константа в шаблоне не может быть указателем на поле, на временный объект, на строковый литерал, на результат typeid
и на стандартную переменную __func__
[17][24];
В for могут быть begin и end разного типа
[править | править код]Теперь for (auto v : x)
означает auto __begin = begin-expr; auto __end = end-expr;
, допуская begin и end разных типов.
Это — база для прохода по диапазонам (ranges), работа над которыми продолжается[25].
Редакционные правки
[править | править код]Понятие «непрерывный итератор»
[править | править код]Массивы std::vector и std::string имеют дело с непрерывными участками памяти. Для них ввели понятие «непрерывный итератор»[26][27]. Концептуально ничего не изменилось.
Дали определения и другим понятиям — forwarding reference, default member initializer, templated entity. Это работа над концепциями Си++20.
Запрещены символы u'x' и U'x', не кодируемые одним символом
[править | править код]Ранее подобное поведение определялось реализацией.
Заодно сделали «символы UTF-8», которые имеют тип char
и могут держать коды от 0 до 127, по аналогии со строками UTF-8 — по видимому, чтобы программа меньше зависела от настроек локали на компьютере[17][28].
Временно запрещён memory_order_consume
[править | править код]Из-за неадекватной семантики метод упорядочивания «consume» устно (без отметки [[deprecated]]
) запретили, призвав пользоваться методом «acquire». Работа над новой семантикой всё ещё ведётся[29], и уже в Си++20 запрет сняли.
В любом случае на PowerPC и ARM все загрузки автоматически будут consume, но не все — acquire, и метод consume может сберечь такты в кроссплатформенном коде[30].
Язык
[править | править код]static_assert с одним аргументом
[править | править код]Если static_assert
не сработал, не всегда требуется сообщать программисту, что не так — часто он и сам может понять из контекста.[31].
static_assert(sizeof(wchar_t) == 2);
inline для глобальных переменных и констант
[править | править код]Теперь можно в заголовочном файле написать inline const ClassName INSTANCE_NAME
и все cpp-файлы будут ссылаться на один объект — в отличие от const ClassName INSTANCE_NAME
или static const ClassName INSTANCE_NAME
.
Новые стандартные аннотации
[править | править код][[fallthrough]]
: в одном из разделов оператораswitch
мы намеренно «проваливаемся» в следующий. Возможная реализация устройства Даффа
int n = (count + 7) / 8; if (!count) return; switch (count % 8) { case 0: do { *to = *from++; [[fallthrough]]; case 7: *to = *from++; [[fallthrough]]; case 6: *to = *from++; [[fallthrough]]; case 5: *to = *from++; [[fallthrough]]; case 4: *to = *from++; [[fallthrough]]; case 3: *to = *from++; [[fallthrough]]; case 2: *to = *from++; [[fallthrough]]; case 1: *to = *from++; } while (--n > 0); }
[[nodiscard]]
: вызов функции как процедуры считается ошибкой — например, это «чистая» функция вродеstring::empty()
[32], вся работа которой заключается в возврате значения, или протокол работы с объектом требует что-то сделать с возвращённым значением, как вunique_ptr::release()
. Атрибут можно прикрепить к типу: любое неиспользование временного объекта — потенциальная ошибка. В более позднем стандарте C++20 можно прикрепить атрибут к конструктору, а также указать причину, почему вызов ошибочен.
class SmartPtr { // собственная реализация unique_ptr public: /// Передаёт управляемый объект под ручное управление /// @return указатель на управляемый объект [[nodiscard]] Payload* release(); }; SmartPtr p; Payload* data = p.release(); // правильное использование умного указателя delete data; p.release(); // warning: ignoring return value of 'SmartPtr::release()', declared with attribute nodiscard (void)p.release(); // так глушат предупреждение // Дескриптор какого-то системного объекта, который в принципе нельзя бросать enum class [[nodiscard]] Handle: size_t { EMPTY = 0 };
[[maybe_unused]]
: в каком-то из режимов компиляции (Windows/POSIX, отладка/выпуск) тот или иной элемент не используется, и это не ошибка.
// Простенькая архитектура передачи текста из системного wstring в QString (UTF-16). template <int Sz> void append(QString& s, unsigned long ch); // версия для Windows, wstring = UTF-16 template<> [[maybe_unused]] inline void append<2>(QString& s, unsigned long ch) { s.append(static_cast<uint16_t>(ch); } // Версию для POSIX append<4> для краткости опустим std::wstring s = L"\U0001F60E"; // смайлик в очках QString r; // Для краткости мы делаем точную копию и столь сложный код не нужен. // Но бывает нужен в какой-нибудь обработке — например, разэкранировании символов. for (auto c : s) append<sizeof(c)>(r, c);
- Или параметр намеренно не используется, но имя оставлено для документирования.
class ISoccerSeason { // интерфейс public: /// @pre обе команды участвуют в этом сезоне. /// @return true, если будет сыгран матч между командой home на своём поле и away в гостях /// @warning В типичном футбольном сезоне обе команды сыграют и на своём, и на чужом поле. virtual bool doTeamsPlay([[maybe_unused]] const Team& home, [[maybe_unused]] const Team& away) const { return true; } virtual ~ISoccerSeason() = default; };
Использование typename во вложенных шаблонах
[править | править код]Недоработка языка Си++: в шаблонах typename
и class
кое-где не взаимозаменяемые[33].
template<template<typename> class X> struct C; // Остаётся OK
template<template<typename> typename X> struct D; // Теперь OK
Оба ключевых слова явно объявлены взаимозаменяемыми.
Структурное связывание
[править | править код]Появился новый способ объявления переменных для распаковки сложных объектов, который получил название структурного связывания[34].
auto [place,wasInserted] = someMap.emplace(key, value);
Работает для пар, кортежей и прочих типов, где работает std::get
.
Запись namespace A::B
[править | править код]Определение вложенных пространств имён:[9][35] namespace A::B {}
как сокращение для namespace A { namespace B {} }
;
Аннотации для пространств имён и элементов перечисляемого типа
[править | править код]Например:
enum class TriBool {
NO,
MAYBE,
YES,
NN [[maybe_unused]],
UNSPECIFIED [[deprecated("Переименован в MAYBE")]] = MAYBE
};
constexpr int TriBool_N = static_cast<int>(TriBool::NN);
const char* triBoolNames[TriBool_N] = { "no", "maybe", "yes" };
Какой-то заявленной цели пока нет[17][36], но это позволит разработчикам компиляторов придумать таковую — например, объявить, что элемент NN особый и его не надо присваивать переменным, обрабатывать в switch
.
If при компиляции
[править | править код]Концепция SFINAE позволила сделать несложный шаблон enable_if
, который обеспечивает разную функциональность для разных типов, но даёт тяжеловесный код. В Си++17 можно упростить программу: оператор if constexpr(expression)
инстанцирует код, если выражение в скобках истинно[37].
template <class T>
constexpr T absolute(T arg) {
return arg < 0 ? -arg : arg;
}
template <class T>
constexpr auto precision_threshold = T(0.000001);
template <class T>
constexpr bool close_enough(T a, T b) {
if constexpr (is_floating_point_v<T>) // << !!
return absolute(a - b) < precision_threshold<T>;
else
return a == b;
}
В данном случае мы убеждаемся, что разница между дробными числами невелика, а целые просто проверяем на равенство.
Упрощённый синтаксис двухместной операции в переменных шаблонах
[править | править код]Упакованные выражения[17][38]:
template<typename... Args> bool foo(Args... args)
{ return (true && ... && args); } // Было
{ return (args && ...); } // Стало
Инициализация локальной переменной в if/switch
[править | править код]Аналогично инициализации локальных переменных в for
, делает код компактнее[39].
if (auto it = m.find(key); it != m.end())
return it->second;
Using в атрибутах
[править | править код]// Было
void f() {
[[rpr::kernel, rpr::target(cpu,gpu)]] // повтор
do_task();
}
// Стало
void f() {
[[using rpr: kernel, target(cpu,gpu)]]
do_task();
}
Бестиповые параметры в шаблонах
[править | править код]Позволяют задавать шаблонные параметры любого типа через auto
[40].
template<auto X> struct B { static constexpr auto value = X; };
B<5> b1; // OK: template parameter type is int
B<'a'> b2; // OK: template parameter type is char
B<2.5> b3; // error: template parameter type cannot be double
Захват лямбда-объектом *this
[править | править код]Было: [self = *this]{ self.f(); }
. Стало: [*this]{ f(); }
[41].
Можно инициализировать enum class числом
[править | править код]enum class
иногда применяется, чтобы сделать другой целый тип, не совместимый ни с чем. Теперь переменные этого типа можно инициализировать числами[42]
enum class Handle : intptr_t { INVALID = 0 };
Handle h { 42 };
Handle h = 42; // запрещено
Гармонизация с Си
[править | править код]Шестнадцатеричное представление дробных чисел
[править | править код]Шестнадцатеричная мантисса и десятичный порядок: 0xC.68p+2, 0x1.P-126
, аналогично формату printf %a
. Си поддерживает этот синтаксис с версии 99[43].
Библиотека
[править | править код]Мелкие доработки библиотеки
[править | править код]- Неконстантная перегрузка
string::data
. Используется для вызова низкоуровневых строковых функций, которые принимают участок памяти определённой длины и заполняют его символами (например, WinAPI). До Си++11 использовалсяconst_cast<char*>(x.data())
, до Си++17 —&x.front()
. emplace_back
одного элемента возвращает ссылку. Позволяет написать такую конструкцию:
v.emplace_back("alpha", "bravo").doSomething();
- Стандартную библиотеку Си обновили с C99 до C11[44].
- Функции
std::size(x)
,std::begin(x)
,std::end(x)
,std::empty(x)
. Позволяют писать общий шаблонный код для контейнеров STL и массивов[26][45]. К тому же std::size — нужная функция, которую ранее часто писали своими силами с ошибками. - Добавлена частичная специализация
bool_constant<bool B> = integral_constant<bool, B>;
[46] - Добавились функции-свойства для SFINAE:
is_swappable
,is_nothrow_swappable
,is_swappable_with
,is_nothrow_swappable_with
,is_aggregate
(составной тип),has_unique_object_representations
(тривиально копируемый объект, и любые два объекта с одинаковым значением имеют одинаковое внутреннее представление). - Расширена библиотека работы с неинициализированной памятью. Появились функции
uninitialized_default_construct
,uninitialized_value_construct
,uninitialized_move
,destroy
,destroy_at
, а также их версии для n элементов.- Функция
std::launder
отключает важное предположение компиляторов: если указатели на виртуальный класс смотрят в один адрес, то у них гарантированно один подтип — а значит, можно агрессивнее подменять виртуальные вызовы статическими там, где этогоlaunder
нет. Также связано с управлением неинициализированной памятью через placement new: на месте объекта-«отца» вдруг появился «сын» или наоборот.
- Функция
- Новый шаблон
void_t<T> = void
. Упрощает создание SFINAE-шаблонов, которые можно раскрыть, если тип T существует[47]. - Для
std::search
добавилась версия с объектом-искателем. По умолчанию существуют три искателя: простейший, Бойер-Мур и Бойер-Мур-Хорспул. - Новая функция
make_from_tuple
инициализирует тип T данными из кортежа. - Новая константа
atomic::is_always_lock_free
определяет, является ли атомарная переменная неблокирующей. - В
chrono
добавили функции округления вверх, вниз и до ближайшего. - В
map/set
добавили функции переброски (merge
) и извлечения (extract
) элементов. - Добавился тип
shared_ptr<T>::weak_type = weak_ptr<T>
. - В некоторых случаях аллокаторы могут иметь неполный тип. Теперь возможны рекурсивные структуры наподобие
struct X { std::vector<X> data; };
. Крупные компиляторы давно поддерживают такое, осталось только заспецифицировать. - Добавились неявные конструкторы в
pair
иtuple
. unique_ptr/shared_ptr
могут работать с Си-массивами (shared_ptr<string[]>(new string[n])
). В Си++14 требовалось протаскивать правильную функцию удаления (shared_ptr<string[]>(new string[n], default_delete<string[]>() )
).- Уточнена работа
common_type
[48][49].
Новый тип std::string_view
[править | править код]Часто бывает нужно передать неизменную строку в другой участок кода, это можно сделать такими методами:
void doSmth(const char *s); // а что, если в строке нулевой символ?
// Да и внутренности функции становятся ошибкоопасными
void doSmth(const std::string &s); // а что, если строка — не string, и придётся выделять память?
В C++17 появился тип string_view
— строка, имеющая только указатель и длину, без владения, управления памятью и даже без завершающего нуля — и поэтому она не имеет функции c_str()
. Изменять можно только границы (начало/длину), но не символы. Задача программиста — сделать, чтобы объект не пережил тот буфер памяти, где хранится строка, и передача параметров — отличное применение для него. Объект string_view
очень маленький (2·битность машины), и его стоит передавать по значению, а не по ссылке.
string_view
сам по себе является абстракцией — он абстрагируется от метода хранения строки, требуя только одно — чтобы текстовые данные были последовательными байтами в памяти. Только сложные необычные структуры (например, строп/канат) хранят строки вразброс. А все остальные — и string
, и const char*
, и разного рода массивы — преобразуются в string_view
.
Размер строки кэша
[править | править код]Есть две новые константы, hardware_constructive_interference_size
и hardware_destructive_interference_size
. Таким образом пользователь может избежать ложного общего доступа (destructive interference) и улучшить локальность (constructive interference).
struct keep_apart {
alignas(hardware_destructive_interference_size) atomic<int> cat;
alignas(hardware_destructive_interference_size) atomic<int> dog;
// cat далеко от dog, их можно менять из разных потоков.
};
struct together {
atomic<int> dog;
int puppy;
};
struct kennel {
//...
alignas(sizeof(together)) together pack;
//...
};
static_assert(sizeof(together) <= hardware_constructive_interference_size);
// убеждаемся, что together занимает одну строку кэша.
Теоретически обе константы должны быть одинаковыми, но для поддержки неоднородных архитектур решено было сделать две константы.[50]
Новый тип shared_mutex
[править | править код]Мьютекс, позволяющий читать параллельно и писать одному[51]. Блокировщики для него называются shared_lock
и unique_lock
.
Автоматическое определение типа параметра контейнера
[править | править код]В библиотеке появились функции, так называемые deduction guides, позволяющие делать такое:
std::pair p(2, 4.5); // 1
std::vector<int> v = {1, 2, 3, 4};
std::vector x(v.begin(), v.end()); // 2
Новые функции вставки в ассоциативный массив с неповторяющимся ключом
[править | править код]Для std::map
и std::unordered_map
добавились две новых функции[52].
#include <string>
#include <map>
class Pair {
public:
int value1, value2;
Pair() : value1(0), value2(0) {}
explicit Pair(int aValue1) : value1(aValue1), value2(0) {}
Pair(int aValue1, int aValue2)
: value1(aValue1), value2(aValue2) {}
};
int main()
{
std::map<std::string, Pair> m;
// Вставить отсутствующий, перезаписать имеющийся
m["a"] = Pair(3, 4); // Си++03 — нужна доп.проверка, была ли перезапись
m.insert_or_assign("a", Pair{3, 4}); // Си++17 — возвращает пару {iterator, bool}
// Вставить отсутствующий, имеющихся не трогать
m.emplace("a", 1); // Си++11 — создаёт временную пару {key, value}
m.try_emplace("a", 1); // Си++17 — не создаёт временной пары {key, value}
return 0;
}
Новые математические функции
[править | править код]Внесены в пространство имён std нестандартные математические функции: beta
, cyl_bessel_i/j/k
, cyl_neumann
, [comp_]ellint_1/2/3
, expint
, hermite
, [assoc_]laguerre
, [assoc_]legendre
, riemann_zeta
, sph_bessel
, sph_legendre
, sph_neumann
[53][54]. За пределами std (в math.h
) их нет.
Из первого предложения (2010): «Мы надеемся, что принятие этого предложения даст посыл разным сообществам вычислителей, что, несмотря на расхожее поверье, Си++ тоже вполне годится для их отрасли». Тогда его не приняли. Сейчас основные производители библиотек (Dinkumware, Boost, GCC) уже имеют эти функции.
Также добавились вычисление НОД[55] и НОК[56], функция приведения в диапазон (clamp
)[57], трёхмерная гипотенуза hypot(x, y, z)
.
Библиотека файловой системы
[править | править код]Библиотека файловой системы, основанная на boost::filesystem
, позволяет:[58]
- автоматическую интернационализацию имён файлов в зависимости от особенностей ОС. Библиотека скрывает, в какой кодировке она работает, и сама конвертирует имена в нужную — как минимум в определённую локалью однобайтовую и различные варианты Юникода;
- проход по каталогам (в том числе рекурсивный);
- определение типов файлов (обычный, каталог, сокет…);
- деление пути к файлу на составные части: диск, каталог, имя и расширение;
- создание каталогов, копирование файлов, удаление каталогов и файлов (в том числе рекурсивное);
- получение имён для временных файлов.
Вариативные типы
[править | править код]Появился класс std::any
, способный содержать данные любого типа[59][60]. От реализаций требуется, чтобы небольшие объекты помещались в any
без выделения памяти. Функция any_cast
требует точного совпадения типа, и any_cast<double>
ничего не даст, если внутри объекта int
.
std::cout << std::boolalpha;
std::any a = 1;
std::cout << a.type().name() << ": " << std::any_cast<int>(a) << std::endl;
a = 3.14;
std::cout << a.type().name() << ": " << std::any_cast<double>(a) << std::endl;
a = true;
std::cout << a.type().name() << ": " << std::any_cast<bool>(a) << std::endl;
// i: 1
// d: 3.14
// b: true
Также есть более простые std::variant<int, bool, double>
(один тип из нескольких заданных) и std::optional<T>
(T или ничего).
Низкоуровневые функции преобразования число-текст
[править | править код]Известный недостаток Си++: для низкоуровневого преобразования чисел в текст без выделения памяти приходится запускать тяжёлую и ненадёжную sprintf
, а встроенное преобразование текста в число, оставшееся с Си, довольно ненадёжно.
Теперь есть встроенные локаленезависимые сверхскоростные from_chars
[61] и to_chars
[62]. Устроены они так, что не требуют (и не производят) закрывающего нуля и могут работать, например, на string_view
. Из-за ограниченности и локаленезависимости предназначены они в первую очередь для JSON и XML, где нужна огромная скорость.
Новый тип polymorphic_allocator
[править | править код]Структуры данных STL (строки, вектора и прочее) содержат шаблонный параметр — аллокатор памяти. Этот аллокатор работает как концепция обобщённого программирования, а не как интерфейс объектно-ориентированного: выделение памяти в куче и пуле даёт разные несовместимые типы. Класс polymorphic_allocator
— стандартное начало для редкой задачи: в зависимости от каких-то условий, выделять память то в куче, то в пуле.
Сам по себе polymorphic_allocator
— не интерфейс, но он связан с интерфейсом memory_resource
.
Новый шаблон std::invoke
[править | править код]Позволяет единообразно вызывать функции, объекты с операцией () (функторы) и лямбда-объекты[63]. Также добавились функции is_invocable
, is_invocable_r
, invoke_result
.
Параллельные версии алгоритмов STL
[править | править код]Для 69 алгоритмов из <algorithm>
, <numeric>
и <memory>
придуманы параллельные версии[64][65][66].
См. также
[править | править код]Ссылки
[править | править код]- Черновик стандарта, N4659, от 21.03.2017
Примечания
[править | править код]- ↑ ISO/IEC 14882:2017 . Дата обращения: 4 декабря 2017. Архивировано 17 мая 2013 года.
- ↑ Recent milestones: C++17 nearly feature-complete, second round of TSes now under development . Дата обращения: 28 марта 2016. Архивировано 8 сентября 2020 года.
- ↑ N3981: Removing trigraphs??! (Richard Smith) (6 мая 2014). Дата обращения: 28 марта 2016. Архивировано 9 июля 2018 года.
- ↑ IBM comment on preparing for a Trigraph-adverse future in C++17 Архивная копия от 11 сентября 2018 на Wayback Machine, IBM paper N4210, 2014-10-10.
- ↑ Remove Deprecated Use of the register Keyword . Дата обращения: 20 августа 2018. Архивировано 14 сентября 2017 года.
- ↑ Remove Deprecated operator++(bool) . Дата обращения: 20 августа 2018. Архивировано 11 сентября 2017 года.
- ↑ Removing Deprecated Exception Specifications from C++17 . Дата обращения: 20 августа 2018. Архивировано 13 сентября 2017 года.
- ↑ N4190: Removing auto_ptr, random_shuffle(), And Old <functional> Stuff (Stephan T. Lavavej) . Дата обращения: 28 марта 2016. Архивировано 20 октября 2017 года.
- ↑ 1 2 3 Updates to my trip report . Дата обращения: 28 марта 2016. Архивировано 19 марта 2015 года.
- ↑ Remove Deprecated iostreams aliases . Дата обращения: 20 августа 2018. Архивировано 22 августа 2017 года.
- ↑ Removing Allocator Support in std::function (rev 1) . Дата обращения: 20 августа 2018. Архивировано 17 сентября 2017 года.
- ↑ Deprecating Vestigial Library Parts in C++17 . Дата обращения: 20 августа 2018. Архивировано 13 сентября 2017 года.
- ↑ Deprecating <codecvt> . Дата обращения: 20 августа 2018. Архивировано 16 сентября 2017 года.
- ↑ Proposed Resolution for CA 14 (shared_ptr use_count/unique) . Дата обращения: 20 августа 2018. Архивировано 7 июля 2017 года.
- ↑ Resolving GB 55, US 84, US 85, US 86 . Дата обращения: 20 августа 2018. Архивировано 5 июля 2017 года.
- ↑ N4259: Wording for std::uncaught_exceptions (Herb Sutter) . Дата обращения: 28 марта 2016. Архивировано 29 ноября 2014 года.
- ↑ 1 2 3 4 5 New core language papers adopted for C++17 . Дата обращения: 28 марта 2016. Архивировано 27 апреля 2015 года.
- ↑ Источник . Дата обращения: 31 мая 2022. Архивировано 16 ноября 2017 года.
- ↑ C++17 should refer to C11 instead of C99 . Дата обращения: 20 августа 2018. Архивировано 13 сентября 2017 года.
- ↑ N3922: New Rules for auto deduction from braced-init-list (James Dennett) . Дата обращения: 28 марта 2016. Архивировано 10 августа 2015 года.
- ↑ Make exception specifications be part of the type system . Дата обращения: 20 августа 2018. Архивировано 12 сентября 2017 года.
- ↑ Dynamic memory allocation for over-aligned data . Дата обращения: 20 августа 2018. Архивировано 8 сентября 2017 года.
- ↑ [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0145r3.pdf Refining Expression Evaluation Order for Idiomatic C++] . Дата обращения: 23 августа 2018. Архивировано 26 августа 2018 года.
- ↑ N4268: Allow constant evaluation for all non-type template arguments (Richard Smith) . Дата обращения: 28 марта 2016. Архивировано 12 марта 2016 года.
- ↑ Generalizing the Range-Based For Loop . Дата обращения: 23 августа 2018. Архивировано 5 октября 2017 года.
- ↑ 1 2 New standard library papers adopted for C++17 . Дата обращения: 28 марта 2016. Архивировано 29 ноября 2014 года.
- ↑ N4284: Contiguous Iterators (Jens Maurer) . Дата обращения: 28 марта 2016. Архивировано 29 ноября 2014 года.
- ↑ N4267: Adding u8 character literals (Richard Smith) . Дата обращения: 28 марта 2016. Архивировано 28 октября 2015 года.
- ↑ Temporarily discourage memory_order_consume . Дата обращения: 20 августа 2018. Архивировано 16 января 2018 года.
- ↑ The Purpose of memory_order_consume in C++11 . Дата обращения: 15 августа 2019. Архивировано 11 ноября 2019 года.
- ↑ N3928: Extending static_assert, v2 (Walter E. Brown) . Дата обращения: 28 марта 2016. Архивировано 11 августа 2015 года.
- ↑ Так, авторы PVS-Studio часто жаловались на ошибку: программист вместо
clear()
писалempty()
. - ↑ N4051: Allow typename in a template template parameter (Richard Smith) . Дата обращения: 28 марта 2016. Архивировано 11 августа 2015 года.
- ↑ Structured binding declaration (since C++17) Архивная копия от 8 сентября 2020 на Wayback Machine en.cppreference.com
- ↑ N4230: Nested namespace definition (Robert Kawulak, Andrew Tomazos) . Дата обращения: 28 марта 2016. Архивировано 3 августа 2015 года.
- ↑ N4266: Attributes for namespaces and enumerators (Richard Smith) . Дата обращения: 28 марта 2016. Архивировано 6 марта 2016 года.
- ↑ constexpr if: A slightly different syntax . Дата обращения: 20 августа 2018. Архивировано 7 октября 2017 года.
- ↑ N4295: Folding expressions (Andrew Sutton, Richard Smith) . Дата обращения: 28 марта 2016. Архивировано 4 апреля 2015 года.
- ↑ Selection statements with initializer . Дата обращения: 12 июня 2019. Архивировано 6 октября 2017 года.
- ↑ Declaring non-type template parameters with auto . Дата обращения: 7 августа 2020. Архивировано 16 сентября 2017 года.
- ↑ Lambda Capture of *this by Value as [=,*this] . Дата обращения: 7 августа 2020. Архивировано 22 августа 2017 года.
- ↑ Construction Rules for enum class Values . Дата обращения: 7 августа 2020. Архивировано 9 декабря 2017 года.
- ↑ Hexadecimal floating literals for C++ . Дата обращения: 12 июня 2019. Архивировано 22 августа 2017 года.
- ↑ C++17 should refer to C11 instead of C99 . Дата обращения: 18 декабря 2016. Архивировано 13 ноября 2016 года.
- ↑ N4280: Non-member size() and more (Riccardo Marcangelo) . Дата обращения: 28 марта 2016. Архивировано 9 марта 2015 года.
- ↑ Wording for bool_constant, revision 1 . Дата обращения: 1 января 2020. Архивировано 14 октября 2017 года.
- ↑ Архивированная копия . Дата обращения: 1 января 2020. Архивировано 28 августа 2017 года.
- ↑ Архивированная копия . Дата обращения: 1 января 2020. Архивировано 10 октября 2017 года.
- ↑ Архивированная копия . Дата обращения: 1 января 2020. Архивировано 5 июля 2017 года.
- ↑ P0154R1 constexpr std::hardware_{constructive,destructive}_interference_size .
- ↑ std::shared_mutex - cppreference.com . Дата обращения: 30 августа 2019. Архивировано 30 августа 2019 года.
- ↑ Improved insertion interface for std::{unordered_,}map (revised) . Дата обращения: 28 марта 2016. Архивировано 27 апреля 2015 года.
- ↑ Архивированная копия . Дата обращения: 20 августа 2019. Архивировано 17 сентября 2019 года.
- ↑ Mathematical Special Functions for C++17, v5 . Дата обращения: 28 марта 2016. Архивировано 5 апреля 2016 года.
- ↑ std::gcd - cppreference.com . Дата обращения: 30 августа 2019. Архивировано 28 марта 2019 года.
- ↑ std::lcm - cppreference.com . Дата обращения: 30 августа 2019. Архивировано 28 марта 2019 года.
- ↑ std::clamp - cppreference.com . Дата обращения: 30 августа 2019. Архивировано 30 августа 2019 года.
- ↑ Filesystem Library Proposal (Beman Dawes) . Дата обращения: 28 марта 2016. Архивировано 20 июля 2016 года.
- ↑ C++ Extensions for Library Fundamentals, Version 2, Working Draft . Дата обращения: 30 августа 2019. Архивировано 25 августа 2019 года.
- ↑ std::any - cppreference.com . Дата обращения: 30 августа 2019. Архивировано 30 августа 2019 года.
- ↑ std::from_chars - cppreference.com . Дата обращения: 30 августа 2019. Архивировано 30 августа 2019 года.
- ↑ std::to_chars - cppreference.com . Дата обращения: 30 августа 2019. Архивировано 30 августа 2019 года.
- ↑ A proposal to add invoke function template (Revision 1) . Дата обращения: 1 января 2020. Архивировано 6 октября 2017 года.
- ↑ Extensions for parallelism - cppreference.com . Дата обращения: 5 февраля 2021. Архивировано 12 ноября 2020 года.
- ↑ The Parallelism TS Should be Standardized . Дата обращения: 28 марта 2016. Архивировано 5 апреля 2016 года.
- ↑ Using C++17 Parallel Algorithms for Better Performance | C++ Team Blog . Дата обращения: 5 февраля 2021. Архивировано 24 января 2021 года.