C++17

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

C++17 — одна з попередніх версій стандарту ISO/IEC для мови програмування C++. Слідує після C++14. Специфікація C++17[1][2] дійшла до чорнової версії стандарту в березні 2017 року і, була остаточно затверджена 8 вересня 2017 року.[3] Cтандарт офіційно опублікований у грудні 2017.[4]

Видалені та заборонені можливості[ред. | ред. код]

  • Видалили register. Слово register все ще залишається зарезервованим, але більше не означає нічого.[7]
  • Видалили ++ для bool. Префіксний та постфіксний інкременти більше не валідні для операцій над типом bool.[8]
  • Видалили throw(A, B, C). Динамічна специфікація виключень для фунцій типу void f() throw(A, B, C); більше не валідна. Залишився throw() як синонім до noexcept(true).[9]
  • Заборонили повторне оголошення статичних constexpr членів класу. Для struct X {static constexpr int n = 10;}; int X::n; вже не є визначенням, а є зайвим, надлишковим оголошенням, яке не рекомендується до використання. Член X::n неявно вбудований (inline).[10]
  • Видалили auto_ptr, random_shuffle, старі функції адаптери з <functional>. Ці можливості були заборонені починаючи з C++11 та замінені на кращі компоненти. Їхні імена залишаються зарезервованими.[11]
  • Видалили заборонені аліаси iostream. Причина така ж як і в попередньому випадку.[12]
  • Видалили конструктори з function які приймають алокатор в якості аргумента. Не тільки семантика була не зрозумілою, але є й технічні проблеми зберігання алокатора в контексті, коли тип не відомий.[13]
  • Заборонили деякі хідери бібліотеки C: <ccomplex>, <cstdalign>, <cstdbool>, <ctgmath>. Але хідер <ciso646> не є забороненим.[14]
  • Заборонили старі бібліотечні компоненти: allocator<void>, raw_storage_iterator, get_temporary_buffer, is_literal_type, std::iterator.[15]
  • Повніcтю заборонили хідер <codecvt>. Він використовувався для перетворення рядкових літералів з одного типу кодування в інший. Проте зробити перетворення правильно було дуже важко, та документація була не правильною. Разом з ним заборонили утиліти wstring_convert та wbuffer_convert з <locale>. Взамін, користувачам рекомендується використовувати спеціалізовані бібліотеки для обробки тексту.[16]
  • Тимчасово заборонили memory_order_consume. Поточна семантика впорядкування роботи з пам'яттю «consume» виявилась неадекватною, впорядкування необхідно перевизначити. Ця робота все ще ведеться. Є сподівання що в наступній версії С++ вона буде готовою. Натомість, користувачам рекомендується використовувати «acquire» впорядкування, щоб не отримати неочікувані результати в майбутньому.[17]
  • Заборонили shared_ptr::unique. Ця функція передбачає поведінку, яка по факту не надається.[18]
  • Заборонили result_of. Натомість треба використовувати invoke_result .[19]

Нові можливості мови з глобальним застосуванням[ред. | ред. код]

Це зміни, які застосовуються без вашого відома або згоди.

  • Специфікація виключень стала частиною системи типів. Специфікація виключень функції стала частиною типу функції: void f() noexcept(true); та void f() noexcept(false); функції з двома різними типами. Вказівники на функції чутливі до специфікації виключень. (Але дві функції f не можуть сформувати перегружений набір). Ця зміна зміцнює систему типів, оскільки дозволяє API вимагати колбеки що не кидають виключень.[20]
  • Гарантований пропуск створення тимчасової копії. Сенс prvalue та glvalue було переглянуто. prvalues більше не є об'єктом, а лише ініціалізацією. Функції, що повертають prvalues більше не створюють копію об'єкта («mandatory copy elision»). Додали нове перетворення prvalue-to-glvalue, яке називається тимчасовою матеріалізацією перетворення. Ця зміна означає що зайва копія не буде створена. Це також стосується типів які не можна копіювати чи переміщати. Це дозволяє оголошувати функції які повертають такі типи.[21]
  • Динамічне виділення пам'яті для даних з надлишковим вирівнюванням. Динамічне виділення пам'яті (operator new) тепер підтримує типи з надлишковим вирівнюванням. Нова перегружена функція приймає параметр вирівнювання.[22]
  • Строгіший порядок обчислення виразу. Порядок обчислення певного підвиразу було визначено краще ніж раніше. Важливим прикладом цієї зміни є те, що аргументи функції тепер вираховуються у невизначеному порядку (indeterminately sequenced). Раніше цього не було в специфікації. Зверніть увагу, що порядок обчислення перегружених операторів залежить від того як вони викликані: коли вони викликаються використовуючи синтаксис оператора, то порядок є таким самим як і для вбудованих операторів, але якщо вони викликаються використовуючи синтаксис виклику функції, то порядок такий самий як і для звичайної функції (тобто невизначений).[23][24]

Нові можливості мови з локальним застосуванням[ред. | ред. код]

Це зміни, які ви можете використовувати

  • Символьний літерал u8, наприклад u8'a'. Такий літерал має тип char і його значення відповідає кодовій точці ISO 10646 (мається на увазі що значення представляє собою один кодовий юніт UTF-8).[25]
  • Шістнадцяткове представлення літералів чисел з рухомою комою (Hexadecimal floating point literals). Літерали чисел з рухомою комою можуть бути записані з шістнадцятковим представлення основи та десятковим представленням експоненти: 0xC.68p+2, 0x1.P-126. Це дозволяє точно (на багатьох платформах) передавати числа з рухомою комою (тобто літерал точно відповідає представленню числа в пам'яті). С підтримує цей синтаксис починаючи з С99, а printf підтримує його через %a.[26]
  • Розгортання запакованих виразів. Зручний синтаксис для ітеративного застосування бінарного оператора до елементів пачки параметрів: template <typename ...Args> auto f(Args ...args) { return (0 + ... + args); }[27][28]
  • template <auto>. Дозволили оголошувати параметри шаблону використовуючи auto[29]. Наприклад:
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
  • Вивід типу аргумента шаблонного класу. Тип аргумента шаблонного класу можна вивести з конструктора. Наприклад pair p(1, 'x'); визначиться як pair<int, char>. Неявний вивід типів виконаний системою згідно з правилами явного виводу типів, що дозволяє розробникам змінювати правила виводу або повністю його заборонити[30][31][32][33]
  • constexpr if. Під час спеціалізації шаблону (під час компіляції), значення виразу в середині if constexpr (condition) інстанціюється тільки тоді, коли виконується condition (який має бути константним виразом).[34]
  • Ініціалізація виразу в умові. В умовах if та switch з'явилася нова, необов'язкова частина, що дозволяє ініціалізувати нову, локальну зміну:[35]
if (auto it = m.find(key); it != m.end()) 
    return it->second;
  • сonstexpr лямбди. Лямбда вирази можуть бути константними виразами: auto add = [](int a, int b) constexpr { return a + b; }; int arr[add(1, 2)];[36]
  • Захоплення лямбдою *this. Раніше [self = *this]{ self.f(); }. Тепер [*this]{ f(); }.[37]
  • inline змінні. Додавання кваліфікатора inline до змінних дозволяє їх визначати в заголовному файлі (механізм аналогічний до inline functions).[38]
  • Структуровані зв'язки. auto [it, ins] = m.try_emplace(key, a1, a2, a3);. Масиви, всі публічні члени класу та типи що підтримують протокол get<N>, такі як pair та tuple розкладаються на елементи, які напряму привласнються оголошеним змінним.[39][40]
  • __has_include. Оператор препроцесора, який перевіряє наявність header файлу.[41]
  • Атрибути [[fallthrough]], [[nodiscard]], [[maybe_unused]]. Новий сет стандартизованих атрибутів. Формально вони не мають строгої семантики, але розробникам компіляторів рекомендується генерувати або пропускати відповідне попередження (warning).[42][43][44]
  • launder. Засіб підтримки мови («межа оптимізації»), що дозволяє бібліотекам повторно використовувати місце зберігання даних, та доступатися до цього місця по старому вказівнику. Раніше це не дозволялося. (Цей засіб розроблений для розробників компіляторів. Він не має використовуватися в «звичайному» коді).[45]
  • Тип byte. Новий тип визначений в <cstddef> (не в <stddef.h>, і тільки в просторі імен std!). Має всі атрибути unsigned char та визначає побітові операції.[46]

Нові можливості бібліотеки[ред. | ред. код]

  • Спеціальні математичні функції. Вміст міжнародного стандарту ISO/IEC 29124:2010 (mathematical special functions) став частиною C++. Функції були додані тільки до <cmath>, але не до <math.h>, та доступні тільки в просторі імен std.[47]
  • Файлова система. Вміст Filesystems Technical Specification став частиною С++. Бібліотека файлової системи дозволяє переносну взаємодію з директоріями та структурами які схожі на директорії (можуть відображати контент, переносити файли і т. д.). В основному моделюється файлова система POSIX, але вона є достатньо гнучкою щоб бути реалізованою для будь-якої іншої системи.[48][49][50][51][52][53]
  • Паралелізм. Вміст Parallelism Technical Specification став частиною С++. Він додає нові перевантажені функції, що приймають додаткові параметри політики виконання алгоритмів. А також повністю нові алгоритми (дивись нижче). Підтримуються три політики виконання, що дозволяють виконувати алгоритм послідовно, паралельно та векторно.[54][55][56][57][58][59][60][61][62][63]
  • Нові алгоритми. Parallelism Technical Specification додав декілька нових алгоритмів до стандартної бібліотеки. Причиною додавання став їх потенціал ефективного, паралельного виконання. Функції доступні в звичній, простій формі: for_each_n, reduce, transform_reduce, exclusive_scan, inclusive_scan, transform_exclusive_scan, transform_inclusive_scan. Зауважте, що reduce виглядає так само як існуючий accumulate, але не гарантує певного порядку виконання операцій.[64]
  • Новий тип: string_view (та basic_string_view). Новий клас string_view є рекомендованим типом для API, які хочуть читати текстовий рядок але не мають наміру володіти ним чи модифікувати. Він створюється з символьного вказівника (char pointer), але інші класи, схожі до текстового рядку, мають пропонувати функції перетворення до string_view.[65][66][67]
  • Новий тип: any. Тип any видяляє тип об'єкту та дозволяє його копіювати. По суті є три речі які ви можете робити з any: 1. задати значення типу T; 2. зробити його копію; 3. запитати чи він містить значення типу U і отримати це значення при умові, коли U це T.[65][68][69]
  • Новий шаблонний клас: variant. Він моделює розділене об'єднання. Тип variant<A, B, C> містить значення якогось одного типу A, B або C в будь-який момент часу.[70][71][72][73][74]
  • Новий шаблонний клас: optional. Значення не є обов'язковим. Тип optional<T> представляє собою або значення типу T, або те, що значення відсутнє (що визначається типом nullopt_t). Деякою мірою це є еквівалентом variant<nullopt_t, T>, але з інтерфейсом, що було спеціально сконструйовано для даної задачі.[65][75][76][77]
  • invoke. Можливіть одинаково викликати сутності, що можуть бути викликаними. Це дозволяє користувачам писати бібліотеки з поведінкою, ідентичною до правила INVOKE.[78]
  • is_invocable, is_invocable_r,invoke_result. Властивості об'єкту. Чи може він бути викликаним та результат виклику.[79][80]
  • Елементарне перетворення тектових рядків. Функції to_chars та from_chars дозволяють створювати або зчитувати текстові рядки, представлені числами. Вони були додані до стандарту як ефективна, низькорівнева заміна операціям форматування printf та iostream. Вони слідують ідеоматичним алгоритмічним стилям С++.[81]
  • Шаблон void_t. template <class...> using void_t = void; Даний псевдонім несподівано користий для метапрограмування. Дозволяє cпростити використання SFINAE.[82]
  • Шаблон bool_constant. template <bool B> using bool_constant = integral_constant<bool, B>[83]
  • Метафункції логічних операції. Метафункції, зі змінною кількістю параметрів для метапрограмування: conjunction, disjunction та negation. Ці властивості важливі в метапрограмуванні: спеціалізації шаблону не створюються якщо від них не вимагають визначити результат.[84]
  • Властивості для SFINAE-сумісного swap. Нові властивості is_swappable, is_nothrow_swappable, is_swappable_with, is_nothrow_swappable_with.[85]
  • Властивість is_aggregate. Вказує чи тип є складеним. Складеними є всі масиви та класи, в яких відсутні конструктори, що були оголошені користувачем, немає приватних або захищених нестатичних членів, відсутні базові класи та віртуальні функції. Властивість користна для того, щоб визначити чи загальний тип може бути створений за допомогою списку ініціалізації {} (list-initialized чи non-list-initialized).[86]
  • Властивість has_unique_object_representations. Якщо T об'єкт, який можна тривіально копіювати, і якщо будь-які два об'єкти типу T з одинаковим значенням мають одинакове представлення об'єкту, то значення has_unique_object_representations буде true. Для будь-якого іншого типу, значення буде false.[87]
  • as_const. Задане lvalue x буде повернуто функцією as_const(x) як константна версія. Не працює з rvalues.[88]
  • Вільні функції size, data та empty. Додаткові функції доповнюють існуючі вільні функції begin/end і т. ін. для доступу до масивів одноманітним чином. Зауважте, що на відміну від begin/end, нові функції не є точками налаштування (customization points[89]) і надаються виключно для зручності.[90]
  • clamp. clamp(x, low, high) повертає x, якщо x знаходиться в інтервалі [low, high]. В противному випадку найближу межу.[91]
  • Клас shared_mutex. Багато агентів виконання можуть одночасно мати право на читання спільного м'ютекса. Але жодний агент виконання не має право на читання, поки інший агент утримує ексклюзивний блок і виконує запис.[93]
  • Розмір лінії кешу. Нові константи 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 {
  // Other data members...
  alignas(sizeof(together)) together pack;
  // Other data members...
};
static_assert(sizeof(together) <= hardware_constructive_interference_size);

Теоретично, значення hardware_constructive_interference_size та hardware_destructive_interference_size має бути одинаковим, але для підтримки неоднорідних архітектур було вирішено зробити дві константи.[94]

  • apply. Викликає функцію або функтор f з аргументами tuple.[65]
int add(int first, int second)
{
    return first + second;    
}
int main()
{
    std::cout << std::apply(add, std::make_tuple(1,2)) << '\n'; // output '3'
}
  • Створення об'єктів з tuple. Нова шаблонна функція make_from_tuple ініціалізує тип Т значеннями елементів кортежу. Нагадує функцію apply, що застосована до конструктора.[95]
  • Універсальний інвертор not_fn. Обгортка, що інвертує результат виклику функції. Працює з об'єктами будь-якої арності, та має замінити старі обгортки not1 та not2.[96][97]
struct LessThan7 : std::unary_function<int, bool>
{
    bool operator()(int i) const { return i < 7; }
};
int main()
{
    std::vector<int> v{0,1,2,3,4,5,6,7,8,9,10};
    std::cout << std::count_if(begin(v), end(v),             LessThan7())  << "\n"; // Output '7'
    std::cout << std::count_if(begin(v), end(v), std::not1  (LessThan7())) << "\n"; // Output '4' (deprecated)
    std::cout << std::count_if(begin(v), end(v), std::not_fn(LessThan7())) << "\n"; // Output '4' (recommended)   
}
  • Ресурси пам'яті memory_resource. Новий набір компонентів що включає в себе базовий клас ресурсу пам'яті (memory_resource) для динамічного обрання провайдерів пам'яті. А також три конкретні реалізації (synchronized_pool_resource, unsynchronized_pool_resource та monotonic_buffer_resource). Дивись нижче варіанти використання.[65]
  • Поліморфний алокатор. Алокатор, що використовує ресурси пам'яті, які можна змінювати під час виконання і які не є частиною типу алокатора. Містить зручний псевдонім std::pmr::vector<T> = std::vector<T, polymorphic_allocator<T>>[65][98]

Зміни до існуючих можливостей[ред. | ред. код]

  • static_assert з одним аргументом. Використання static_assert більше не вимагає другого аргументу: static_assert(N > 0);.[100]
  • Оголошення вкладених namespace. Наприклад: namespace X::Y { … } замість namespace X { namespace Y { … }}[101]
  • Дозволили використовувати typename в шаблоні який знаходиться в середині параметрів другого шаблона (template <template <typename> typename Tmpl> struct X;). Раніше шаблонні параметри шаблону були змушені використовувати ключове слово class.[102]
  • Оператор for приймає параметри begin/end різних типів. Переписане правило для for (decl : expr) тепер каже auto __begin = begin-expr; auto __end = end-expr; замість auto __begin = begin-expr, __end = end-expr;. Це створює основу для майбутньої підтримки оператором for діапазонів (ranges), робота над якими ще триває.[103]
  • Розгортання пачки параметрів типів в оголошеннях using. template <typename ...Args> struct X : Args... { using Args::f...; };[104]
  • Ініціалізація значень фіксованих перелічень (fixed-enums). C++11 додав можливість оголошення нового типу цілих чисел, який не може неявно перетворюватися в інший тип. Ця техніка дуже корисна якщо потрібно уникнути анархічних, неявних перетворень С++, що були успадковані з С. Проте існувала одна незручність: ініціалізація значення нового типу вимагала використання static_cast або функціональної нотатки (b = int (a);). Цим виправленням дозволили використовувати спрощену форму ініціалізації фіксованих перелічень.[105]

Наприклад

enum class Index : uint32_t { }; 

int main()
{
    Index i1 { Index(5) }; // C++11 OK
    Index i2 { 5 };        // C++11 error: cannot convert 'int' to 'Index' in initialization
    Index i3 { 5 };        // C++17 OK
}
  • uncaught_exceptions(). Функція uncaught_exception уже не підтримується. Нова функція uncaught_exceptions повертає кількість винятків, замість true/false. Попередня функція була непридатною до використання, дивись N4152 для подальшої інформації.[106]
  • Атрибути в іменних просторах та переліченнях. Тепер в іменний простір та перелічення можна додати коментар з атрибутом. Це дозволяє, наприклад, позначити параметр як застарілий.[107]
enum OperationMode {
  OM_Invalid,
  OM_Normal,
  OM_Terrified [[deprecated("re-named to invalid")]],
  OM_AbortOnError  [[deprecated("exceptions are used instead")]] = 4
};
namespace [[deprecated]] old_stuff{
    void legacy();
}
  • Можна використовувати using для іменних просторів атрибутів. Тепер замість:
void f() {
    [[rpr::kernel, rpr::target(cpu,gpu)]] // repetition
    do-task();
}

Можна писати так:

void f() {
    [[using rpr: kernel, target(cpu,gpu)]]
    do-task();
}

Це спрощення може допомогти, коли ви створюєте інструменти для автоматичного перекладу такого коду в іншу програмну модель.[108]

  • Покращено вставку в асоціативні контейнери. my_map.try_emplace(key, arg1, arg2, arg3) нічого не робить якщо ключ уже існує в контейнері, в іншому випадку створює новий елемент. Інтерфейс гарантує, що rvalue reference аргументи не будуть переміщені, якщо вставка не відбулась.[109]
  • Змінено тип, який повертає функція emplace. Послідовні контейнери які мають функції emplace_front та emplace_back раніше нічого не повертали (void emplace_front(…);). Тепер вони повертають зсилку на щойно створений елемент. (Ця зміна не вплинула на асоціативні контейнери, оскільки вони і раніше, завжди повертали ітератор на вставлений елемент).[110]
  • Об'єднання асоціативних контейнерів (map та set). До бібліотеки контейнерів додано новий механізм, що дозволяє переносити елементи між різними об'єктами map/set.[111][112]
set<int> src{1, 3, 5};
set<int> dst{2, 4, 5};
dst.merge(src); // Merge src into dst.
// src == {5}
// dst == {1, 2, 3, 4, 5}

Ця техніка також дозволяє змінювати ключ:

map<int, string> m{{1,mango}, {2,papaya}, {3,guava}};
auto nh = m.extract(2);
nh.key() = 4;
m.insert(move(nh));
// m == {{1,”mango”}, {3,”guava”}, {4,”papaya”}}
  • Неконстантний string::data. Додали неконстантну перегрузку до basic_string::data що повертає вказівник на дані які можна модифікувати.[113]
  • Версія lock_guard зі змінною кількістю аргументів називається scoped_lock. Новий шаблонний клас зі змінною кількістю аргументів scoped_lock<Args...> одночасно захоплює декілька об'єктів синхронізації, використовуючи такий самий алгоритм як lock та звільняє їх в деструкторі. Спершу, пропонувалося змінити визначення lock_guard, щоб додати можливість приймати змінну кількість аргументів, але виявилося, що ця зміна ламає існуючу поведінку. Тому, взамін, ми отримали новий клас scoped_lock, який однозначно кращий ніж старий lock_guard та має використовуватися замість нього.[114][115]
  • _v<T> шаблонні змінні. Добавлені some_trait_v<T> шаблонні змінні із значенням some_trait<T>::value для type trait стандартної бібліотеки..[116]
  • atomic::is_always_lock_free. Новий константний, статичний член is_always_lock_free документує чи операції з даним атомарним типом завжди вільні від блокувань (lock-free). Існуюча нестатична функція класу is_lock_free може повертати різні відповіді для різних значень атомарного типу.[117]
  • shared_ptr для масивів. Шаблонний клас shared_ptr тепер підтримує масиви в стилі С. Для цього конструктору треба передати T[] або T[N] як параметр шаблону, а конструктор shared_ptr сам визначить відповідну функцію для очищення пам'яті.[65][118]
using std::string;
using std::shared_ptr;
using std::default_delete;
int arr_size{};

// C++14
auto string_arr_sptr_cpp14 = shared_ptr<string[]>(new string[arr_size], default_delete<string[]>() );
string_arr_sptr_cpp14.reset(new string[arr_size], default_delete<string[]>() );
// define an explicit deleter, 
// or otherwise, "delete ptr;" will internally be used incorrectly!

// C++17
auto string_arr_sptr_cpp17 = shared_ptr<string[]>(new string[arr_size]);
string_arr_sptr_cpp17.reset(new string[arr_size]);
  • shared_ptr::weak_type. До класу shared_ptr<T> додали нове поле weak_type, який є синонімом weak_ptr<T>. Це дозволяє конструювати weak_ptr з shared_ptr без явного вказання типу weak_ptr.[119]
  • Тривимірна гіпотенуза. Додано hypot(x, y, z), як додатковий набір перегружених функцій, до <cmath> (але не до <math.h>, та тальки у простір імен std).[120]
  • Додаткові алгоритми роботи з неініціалізованою пам'яттю. Додаткові алгоритми для створення об'єктів в неініціалізованій пам'яті та для видалення об'єктів. Керування пам'яттю без використання алокаторів, що надаються стандартною бібліотекою, є поширеною практикою як серед бібліотек користувачів, так і в самій стандартній бібліотеці. Наприклад, можна використовувати внутрішні буфери, або використовувати алокатори що не керують життєвим циклом об'єкта: bde, sgi, eastl, bitsquid. Написання власних алокаторів досить складна задача, тому мати декілька реалізацій таких алгоритмів допоможе розробникам бібліотек написання коректного та високоефективного коду. Було додано наступні алгоритми:
    • destroy_at, destroy та destroy_n — викликають деструктор для конкретного елемента.
    • uninitialized_move та uninitialized_move_n — виконують створення елементів переміщенням (move construction) для діапазону пам'яті. Схоже на uninitialized_copy
    • uninitialized_value_construct та uninitialized_value_construct_n — виконують ініціалізацію об'єктів значеннями для діапазону пам'яті.
    • uninitialized_default_construct та uninitialized_default_construct_n — виконують ініціалізацію об'єктів значеннями за замовчуванням для діапазону пам'яті.[121]
  • Підтримка неповних типів для алокаторів. Ця зміна послаблює вимоги до алокаторів мати повний тип, що дозволяє використовувати такі рекурсивні структури як struct X { std::vector<X> data; };.[122]
  • Зміни до <chrono>. Додали округлення вгору, вниз та до найближчого цілого для часових точок (floor, ceil, round). Зробили більшість функцій constexpr.[123][124]
  • constexpr для char_traits. Всі спеціалізації необхідні для char_traits тепер мають constexpr функції-члени length, compare, find та assign. Це дозволить більш широко використовувати текстові рядки в константних виразах.[125]
  • Покращили pair та tuple. Ця зміна робить конструктори pair та tuple такими ж явними, як і відповідний тип елементу конструктора.[126] Тепер можна писати так:
std::tuple<int, int> pixel_coordinates() 
{
  return {10, -15};  // OK
}
  • Уточнена робота common_type.[127][128]

Різне[ред. | ред. код]

  • С++ тепер посилається на С11. Стандарт С++ тепер нормативно посилається на С11 (ISO/IEC 9899:2011) як «Стандарт С». Не тільки ISO вимагає, щоб посилання на інші міжнародні стандарти посилались на останню опубліковану версію, а не історичну версію, але це також дає доступ до aligned_alloc, який корисний для вдосконалення менеджменту динамічної пам'яті.[129]
  • Зарезервували іменні простори. Всі першорівневі простори імен вигляду stdX, де X це послідовність чисел, зарезервовані.[130]
  • Короткий огляд бібліотеки С. Чисто редакційна зміна. Раніше, всі заголовки в частині «Бібліотека С» були представлені простим списком імен. Тепер це було змінено на детальний опис. Це робить зміни в семантиці С простішими до врахування в С++.[131]
  • Визначення термінів «forwarding reference», «default member initializer», «templated entity» та «contiguous iterator». Ці зміни не мають нормативного впливу, але вони визначають офіційну термінологію для концептів, які тільки починають виникати з мовних правил. Точні та добре визначені терміни спрощують розмови про С++ та написання специфікації.[132][133][134][135]
  • Заміна «генератор випадкових чисел» на «генератор випадкових бітів». Аналогічно, заміна не має нормативного впливу, але роз'яснює дизайн та наміри бібліотеки <random>.[136]

Наступний стандарт[ред. | ред. код]

Див. також[ред. | ред. код]

Примітки[ред. | ред. код]

  1. N4661 Editors' Report -- Programming Languages -- C++. 21 March 2017. Процитовано 2017-03-21. 
  2. ISO/IEC DIS 14882: Programming Languages — C++. Архів оригіналу за 2017-03-25. 
  3. C++17 is formally approved. 
  4. ISO/IEC 14882:2017. 
  5. N3981: Removing trigraphs??! (Richard Smith). 2014-05-06. 
  6. IBM comment on preparing for a Trigraph-adverse future in C++17, IBM paper N4210, 2014-10-10. Authors: Michael Wong, Hubert Tong, Rajan Bhakta, Derek Inglis
  7. Remove Deprecated Use of the register Keyword. 
  8. Remove Deprecated operator++(bool). 
  9. Removing Deprecated Exception Specifications from C++17. 
  10. Inline Variables. 
  11. Removing auto_ptr, random_shuffle(), And Old <functional> Stuff. 
  12. Remove Deprecated iostreams aliases. 
  13. Removing Allocator Support in std::function (rev 1). 
  14. C++17 should refer to C11 instead of C99. 
  15. Deprecating Vestigial Library Parts in C++17. 
  16. Deprecating <codecvt>. 
  17. Temporarily discourage memory_order_consume. 
  18. Proposed Resolution for CA 14 (shared_ptr use_count/unique). 
  19. Resolving GB 55, US 84, US 85, US 86. 
  20. Make exception specifications be part of the type system. 
  21. Wording for guaranteed copy elision through simplified value categories. 
  22. Dynamic memory allocation for over-aligned data. 
  23. Refining Expression Evaluation Order for Idiomatic C++. 
  24. c++ - What are the evaluation order guarantees introduced by C++17?. Stack Overflow. Процитовано 2019-02-07. 
  25. Adding u8 character literals. 
  26. Hexadecimal floating literals for C++. 
  27. Unary Folds and Empty Parameter Packs (revision 1). 
  28. Folding expressions. 
  29. Declaring non-type template parameters with auto. 
  30. Template argument deduction for class templates (Rev. 6). 
  31. Toward a resolution of US7 and US14: Integrating template deduction for class templates into the standard library. 
  32. Class Template Argument DeductionAssorted NB resolution and issues. 
  33. Drafting for class template argument deduction issues. 
  34. constexpr if: A slightly different syntax. 
  35. Selection statements with initializer. 
  36. Wording for Constexpr Lambda. 
  37. Lambda Capture of *this by Value as [=,*this]. 
  38. Inline Variables. 
  39. P0217R3: Proposed wording for structured bindings. 
  40. P0615R0: Renaming for structured bindings. 
  41. __has_include for C++17. 
  42. Wording for [[fallthrough]] attribute. 
  43. Wording for [[nodiscard]] attribute. 
  44. Wording for [[maybe_unused]] attribute. 
  45. Core Issue 1776: Replacement of class objects containing reference members. 
  46. A byte type definition. 
  47. Mathematical Special Functions for C++17, v5. 
  48. Adopt the File System TS for C++17. 
  49. Relative Paths for Filesystem (R1). 
  50. Directory Entry Caching for Filesystem (R1). 
  51. Adapting string_view by filesystem paths. 
  52. P0430R2 – File system library on non-POSIX-like operating systems. 
  53. Proposed Resolution of C++17 National Body Comments for Filesystems(R2). 
  54. The Parallelism TS Should be Standardized. 
  55. Better Names for Parallel Execution Policies in C++17. 
  56. P0394-r4: Hotel Parallelifornia: terminate() for Parallel Algorithms Exception Handling. 
  57. P0452r1 Unifying <numeric> Parallel Algorithms. 
  58. Iterator Concerns for Parallel Algorithms. 
  59. P0502r0 Throwing out of a parallel algorithm terminates—but how?. 
  60. P0518r1 Allowing copies as arguments to function objects given to parallel algorithms in response to CH11. 
  61. P0523R1: Wording for CH 10: Complexity of parallel algorithms. 
  62. P0574r1: Algorithm Complexity Constraints and Parallel Overloads. 
  63. P0623r0 Final C++17 Parallel Algorithms Fixes. 
  64. The Parallelism TS Should be Standardized. 
  65. а б в г д е ж и Adopt Library Fundamentals V1 TS Components for C++17 (R1). 
  66. Integrating std::string_view and std::string. 
  67. Literal suffixes for basic_string_view. 
  68. Revisiting in-place tag types for any/optional/variant. 
  69. Homogeneous interface for variant, any andoptional (Revision 3). 
  70. Variant: a type-safe union for C++17 (v8). 
  71. Disallowing references, incomplete types, arrays, and empty variants. 
  72. Revisiting in-place tag types for any/optional/variant. 
  73. Homogeneous interface for variant, any andoptional (Revision 3). 
  74. Making Variant Greater Equal. 
  75. Making Optional Greater Equal Again. 
  76. Homogeneous interface for variant, any andoptional (Revision 3). 
  77. Revisiting in-place tag types for any/optional/variant. 
  78. A proposal to add invoke function template (Revision 1). 
  79. is_callable, the missing INVOKE related trait. 
  80. Resolving GB 55, US 84, US 85, US 86. 
  81. P0067R5: Elementary string conversions, revision 5. 
  82. TransformationTrait Alias void_t. 
  83. Wording for bool_constant, revision 1. 
  84. Logical Operator Type Traits (revision 1). 
  85. Adding [nothrow-]swappable traits, revision 3. 
  86. C++ Standard Library Defect Report List (Revision D106). 
  87. has_unique_object_representations - wording. 
  88. Constant View: A proposal for a std::as_const helper function template. 
  89. Customization Point Design in C++11 and Beyond. 
  90. Non-member size() and more (Revision 2). 
  91. An algorithm to "clamp" a value between a pair of boundary values (revision 1). 
  92. Adopt Selected Library Fundamentals V2 Components for C++17. 
  93. N4508: A proposal to add shared_mutex (untimed). 
  94. P0154R1 constexpr std::hardware_{constructive,destructive}_interference_size. 
  95. P0209r2 | make_from_tuple: apply for construction. 
  96. Adopt not_fn from Library Fundamentals 2 for C++17. 
  97. Fixes for not_fn. 
  98. P0337r0 | Delete operator= for polymorphic_allocator. 
  99. Fixing a design mistake in the searchers interface in Library Fundamentals. 
  100. Extending static_assert, v2. 
  101. Nested namespace definition (revision 2). 
  102. Allow typename in a template template parameter. 
  103. Generalizing the Range-Based For Loop. 
  104. Pack expansions in using-declarations. 
  105. Construction Rules for enum class Values. 
  106. Wording for std::uncaught_exceptions. 
  107. Attributes for namespaces and enumerators. 
  108. Using attribute namespaces without repetition. 
  109. Improved insertion interface for unique-key maps (Revision 2.3). 
  110. Emplace Return Type (Revision 2). 
  111. Splicing Maps and Sets (Revision 5). 
  112. Wording for GB 58. 
  113. Give 'std::string' a non-const '.data()' member function. 
  114. Variadic lock_guard (Rev. 3). 
  115. Variadic lock_guard (Rev. 5). 
  116. Adopt Type Traits Variable Templates from Library Fundamentals TS for C++17. 
  117. P0152R1 constexpr atomic<T>::is_always_lock_free. 
  118. Merging shared_ptr changes from Library Fundamentals to C++17. 
  119. shared_ptr::weak_type. 
  120. Proposal to Introduce a 3-Argument Overload to std::hypot. 
  121. Extending memory management tools. 
  122. Minimal incomplete type support for standard containers, revision 4. 
  123. Difference from previous revision. 
  124. Wording for GB 50. 
  125. Constexpr for std::char_traits. 
  126. Improving pair and tuple, revision 3. 
  127. Resolving LWG Issues re common_type. 
  128. common_type and duration. 
  129. C++17 should refer to C11 instead of C99. 
  130. Reserve a New Library Namespace Future Standardization. 
  131. Synopses for the C library. 
  132. Wording for Forwarding References. 
  133. Introducing a name for brace-or-equal-initializers for non-static data members. 
  134. P0391R0: Introducing the term "templated entity". 
  135. N4284: Contiguous Iterators. 
  136. A <random> Nomenclature Tweak. 
  137. https://herbsutter.com/2016/06/30/trip-report-summer-iso-c-standards-meeting-oulu/ «the next standard after C++17 will be C++20»
  138. Current Status : Standard C++. 
  139. https://botondballo.wordpress.com/2017/08/02/trip-report-c-standards-meeting-in-toronto-july-2017/

Посилання[ред. | ред. код]