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... As> bool foo(As... 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>
.
Низкоуровневые функции преобразования число-текст
[править | править код]Известный недостаток Си : для низкоуровневого преобразования чисел в текст без выделения памяти приходится запускать тяжёлую и ненадёжную 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 года.