C++20

Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od verze recenzované 17. ledna 2022; kontroly vyžadují 135 úprav .

C++20  je název normy ISO /IEC pro programovací jazyk C++ . Specifikace byla zveřejněna v prosinci 2020 [1] .

Výbor pro standardy C++ začal plánovat C++20 v červenci 2017 [2] . C++20 je nástupcem C++17 .

Konstanta se zvýšila na . __cplusplus202002L

Zakázáno a odstraněno

Operace s volatile jsou zakázány

Modifikátor je samozřejmě závislý na stroji - pro komunikaci s vybavením. Není tedy jasné, jaká je sémantika té či oné operace a kolik paměťových přístupů bude. Pro synchronizaci mezi vlákny je lepší použít . volatileatomic

Následující operace s -proměnnými jsou zakázány [3] : volatile

atomicByly přidány další funkce, které kompenzují to, co bylo zakázáno .

Byla odstraněna inicializace agregace, když existuje vlastní konstruktor

V předchozích standardech byla agregovaná inicializace povolena, pokud byl konstruktor označen jako nebo , což uživatele uvedlo v omyl: objekt je inicializován obcházením konstruktoru. defaultdelete

struktura X { int a = 0 ; x () = výchozí ; }; X x { 5 }; // C++17: OK // C++20: žádný odpovídající konstruktor pro inicializaci 'X'

Odstraněny zákazy z C++17

Odstraněny vzácné standardní funkce knihovny zakázané v C++ 17: [4] [5] [6]

  • allocator<void> - se ukázalo jako nevyžádané;
  • některé funkce allocator jsou duplikovány šablonou allocator_traits;
  • raw_storage_iterator - nevolá konstruktory, a proto je aplikace omezená;
  • get_temporary_buffer - má nezřejmá úskalí;
  • is_literal_type - nepoužitelný pro generický kód;
  • shared_ptr::unique() - kvůli nespolehlivosti ve vícevláknovém prostředí; pokud to opravdu potřebujete, použijte ;use_count
  • result_of - nahrazeno invoke_result;
  • uncaught_exception() - nahrazeno uncaught_exceptions.
  • <ccomplex>, <ciso646>, <cstdalign>, <cstdbool>, <ctgmath> — nemají v C++ žádný význam. a další ponechány pro kompatibilitu s C.<complex.h>

Tato poznámka byla odstraněna z jazyka , který byl v C++11 nahrazen jazykem . Pokud potřebujete kompatibilitu s C++03, musíte napsat něco jako throw()noexcept

#if __cplusplus < 201103L #define noexcept throw() #endif

Vlevo, odjet:

  • codecvt - ve skutečnosti to fungovalo velmi špatně, komise vyzvala k využití specializovaných knihoven.
  • iterator - je jednodušší psát iterátory od začátku, než na nich stavět.
  • proudy  - není jasné, co je na oplátku.char*
  • implicitní vytvoření operace "přiřadit", pokud existuje konstruktor kopírování a destruktor (a také konstruktor kopírování, pokud existuje přiřazení a destruktor) - knihovna stále spoléhá na toto chování.

Další zákazy z jazyka

  • Implicitní zachycení ve funkcích lambda  - kvůli nejasné sémantice. Existuje pro snímání pomocí ukazatele a snímání pomocí kopie.*this[](){ std::cout << myField; }[this](){ std::cout << myField; }[*this](){ std::cout << myField; }
  • Operace "čárka" v indexech pro libovolné a, b a c je způsobena nezřejmým chováním a touhou vytvořit novou syntaxi pro vícerozměrná pole [7] . Pokud to opravdu potřebujete, napište .a[b,c]a[(b,c)]
  • Implicitní konverze na výčtový typ – pro předvídatelnější chování nové operace hvězdné lodi ( , srovnání se třemi hodnotami).<=>
  • Porovnání dvou polí - pro předvídatelnější chování nové operace "hvězdná loď" ( , třímístné srovnání). Alespoň jeden musí být převeden na ukazatel.<=>

Další zákazy z knihovny

  • is_pod - namísto složitého konceptu „ jednoduché datové struktury “ je lepší použít specifické vlastnosti typu: je triviálně postaven, triviálně zničen atd. Pokud je to velmi nutné (např. přenos dat mezi pluginy ), je ekvivalentní k .is_trivial && is_standard_layout
  • std::rel_ops Nová operace Starship to dělá lépe.
  • atomové schopnosti  - není jasné, jak pracovat s ukazatelem, atomicky nebo ne. Je lepší to definovat pomocí typového systému, .shared_ptratomic<shared_ptr>
  • string::capacity() - nyní rozhodl, že nebude snižovat kapacitu.reserve
  • filesystem::u8path — se nyní liší od .u8stringstring
  • ATOMIC_FLAG_INIT, atomic_init, ATOMIC_VAR_INIT — nyní to dělá konstruktor šablon .atomic

Jazyk

Drobné změny

  • Přidán nepodepsaný typ char8_t schopný obsahovat jednotky UTF-8 .
  • using EnumClass, což umožňuje, aby byl kód na klíčových místech méně nepřehledný.
  • Dodatečná inicializace v pro podle objektu: [8] . Pokud je vrácený objekt dočasný , jeho životnost se prodlouží na celý cyklus, ale ostatní dočasné objekty budou bezpečně odstraněny, a pokud je f() pravdivé, zápis je chybný.for (T thing = f(); auto& x : thing.items())items()for (auto& x : f().items())

Moduly

Direktiva kompilátoru #includebyla svého času pohodlným mechanismem C, což byl ve skutečnosti multiplatformní assembler, který „parazitoval“ na nástrojích assembleru – linkeru a knihovníku. Proto důležitá vlastnost kompilátorů C - byly první, které se po assembleru objevily na nových platformách. S rozšiřováním projektů se však doba jejich kompilace kvadraticky prodloužila: zvýšil se jak počet překladových jednotek , tak počet k nim připojených hlaviček. Modulový mechanismus je již od dob C++11 dlouhodobým předmětem sporů.

Vstoupilo do C++20 takto [9] :

// helloworld.cpp exportní modul helloworld ; // import deklarace modulu < iostream > ; // deklarace importu export void hello () { // deklarace exportu std :: cout << "Ahoj světe! \n " ; }

Coroutines

Korutina  je speciální bezzásobníková funkce, která může pozastavit své provádění, zatímco je vykonávána jiná funkce [10] . Stav korutiny je uložen v paměti haldy (pokud se optimalizátoru nepodařilo alokaci zbavit). Vypadá jako běžná funkce, ale obsahuje speciální klíčová slova coroutine . co_*

task <> tcp_echo_server () { char data [ 1024 ]; pro (;;) { size_t n = co_await socket . async_read_some ( buffer ( data )); co_await async_write ( socket , buffer ( data , n )); } }

Fyzicky je coroutine funkcí, která vrací čerstvě vytvořený objekt slibu. Pokaždé, když uživatel něco udělá s objektem slibu, řízení se přenese do kódu korutiny. V knihovně je k dispozici několik standardních příslibů - například poskytuje líné hodnocení . lazy<T>

název_typu je prohlášen za redundantní, kde je povolen pouze typ

Na některých místech šablon už slovo typename(vysvětlující, že jde  o typ a ne o funkci) není vyžadováno [11] . Mezi tato místa patří… Object::Thing

  • zadejte po  -newauto x = new Object::Thing;
  • zadejte  -usingusing Thing = Object::Thing;
  • konečný návratový typ ;auto f() -> Object::Thing
  • výchozí typ v šablonětemplate<class T = Object::Thing> T f();
  • zadejte static_cast , const_cast , reinterpret_cast , dynamic_cast  —auto x = static_cast<Object::Thing>(y);
  • typ proměnné/funkce ve jmenném prostoru (včetně globálního) nebo třídy —Object::Thing variable;
  • typ parametru funkce/šablony, pokud existuje identifikátor (kromě výrazů souvisejících s výpočtem výchozí hodnoty parametru) —void func(Object::Thing x);
šablona < třída T > T :: Rf ( ); // OK nyní, zadejte šablonu globálního jmenného prostoru < class T > void f ( T :: R ); // Potřebujete název typu, bez něj je to pokus o vytvoření proměnné void inicializované pomocí šablony T::R < class T > struct S { pomocí Ptr = PtrTraits < T >:: Ptr ; // Nyní OK, zadejte pomocí T :: R f ( T :: P p ) { // Nyní OK, zadejte class return static_cast < T :: R > ( p ); // Nyní OK, static_cast } auto g () -> S < T *>:: Ptr ; // OK nyní, konečný návratový typ }; template < typename T > void f () { void ( * pf )( T :: X ); // Zůstává v pořádku, proměnná typu void* inicializována pomocí T::X void g ( T :: X ); // Potřebujete název typu, bez něj je to pokus o vytvoření proměnné void inicializované pomocí T::X }

Výpočet velikosti pole v new

Velikost pole v operátoru new se nyní automaticky odečítá [12]

double a []{ 1 , 2 , 3 }; // Zůstává v pořádku double * p = new double []{ 1 , 2 , 3 }; // Teď OK

Nové atributy

  • [[no_unique_address]] - proměnná bez dat nesmí zabírat místo a další proměnné mohou být uloženy v „otvorech“ proměnné s daty. Ale: proměnné stejného typu nemohou být nikdy na stejné adrese.
šablona < class Allocator > class Storage { soukromé : [[ no_unique_address ]] Allocator alloc ; };
  • [[nodiscard("причина")]] je rozšířením stejnojmenného atributu C++17. Označuje, že návratová hodnota funkce by neměla být ignorována, a vydává důvod.
class XmlReader { // čtečka typu XML stream public : [[ nodiscard ( "Zkontrolujte výsledek nebo použijte requireTag" )]] bool getTag ( const char * name ); void requireTag ( const char * název ) { if ( ! getTag ( name )) throw std :: logic_error ( std :: string ( "requireTag: " ) + jméno + " nenalezeno" ); } };
  • [[likely]] / [[unlikely]] - všimněte si, pod kterými větvemi je nutné optimalizovat program pro co nejlepší práci větveného prediktoru . Tato technika je ve skutečnosti již implementována v některých kompilátorech, viz __builtin_expectnapříklad GCC.
if ( x > y ) [[ nepravděpodobné ]] { std :: cout << "Zřídka se stává" << std :: endl ; } jinde [[ pravděpodobné ]] { std :: cout << "Často se stává" << std :: endl ; }

Rozšířený constexpr

Constexpr umožňuje:

  • volání virtuálních funkcí [13] ;
  • volání destruktorů, které musí být také ;constexpr
  • pracovat s union[14] ;
  • práce s  - blok intercept nedělá nic a vyvoláním výjimky v tomto kontextu, jako předtím, se funkce vypočítá během provádění [15] ;try
  • použití a [16] ;dynamic_casttypeid
  • new, s určitými omezeními [17] ;
  • asmpokud není volána při kompilaci;
  • neinicializované proměnné.

Teoreticky taková konstrukce umožní například vytvořit konstantní std::vector jednoduše ukázat na paměť odpovídajícího std::initializer_list a běžnou nekonstantní alokovanou dynamickou paměť.

Rozšířená volání funkce lambda v době kompilace - například můžete třídit std::tuple .

Klíčová slova consteval a constinit

kód constexpr není nutné volat při kompilaci a stačí jej zapsat tak, aby se řetězec constexpr přerušil v konstruktoru std::set a při spuštění došlo k inicializaci. Někdy je to nežádoucí - pokud se proměnná používá při inicializaci programu (známá nevýhoda C++ - nekontrolované pořadí inicializace souborů CPP), velká (například velká tabulka) nebo obtížně vypočítatelná (inicializace stejného tabulka, která má O (n²)). A programátoři mají jen sportovní zájem o převod kódu do kompilace. Aby byla zajištěna jistota, jsou použita dvě nová klíčová slova: std::set<std::string_view> dic { "alpha", "bravo" };

  • constevalve funkcích: vyžaduje, aby byla funkce provedena při kompilaci. Volání z kontextu, který není spustitelný během kompilace, není povoleno. V hlavičkách kompatibility se staršími kompilátory nahrazeno .constexpr
  • constinitv proměnné: vyžaduje, aby byla proměnná vyhodnocena při kompilaci. Nahrazeno prázdným řetězcem v záhlaví kompatibility se staršími kompilátory.
consteval int sqr ( int n ) { return n * n ; } const auto res2 = sqr ( 5 ) ; int main () { int n ; std :: cin >> n ; std :: cout << sqr ( n ) << std :: endl ; // chyba, nevyčíslitelná při kompilaci }

explicitní (bool)

Klíčové slovo lze zapsat společně s booleovským konstantním výrazem: pokud je pravdivý, převod je možný pouze explicitně. Zjednodušuje metaprogramování, nahrazuje idiom SFINAE [18] . explicit

// Bylo, std::forward vynecháno kvůli stručnosti šablony < class T > struct Wrapper { šablona < class U , std :: enable_if_t < std :: is_convertible_v < U , T >>* = nullptr > Obálka ( U const & u ) : t_ ( u ) {} šablona < class U , std :: enable_if_t <! std :: is_convertible_v < U , T >>* = nullptr > explicitní obal ( U const & u ) : t_ ( u ) {} Tt_ ; _ }; // Stala se šablonou < class T > struct Wrapper { template < class U > explicit ( ! std :: is_convertible_v < U , T > ) Wrapper ( U const & u ) : t_ ( u ) {} Tt_ ; _ };

Třímístné srovnání ("hvězdná loď")

Operace vám umožňuje porovnávat objekty pomocí jedné ze tří metod: <=>

  • Částečné pořadí : menší než, ekvivalentní, větší než, nesrovnatelné.
  • Slabé pořadí : menší než, ekvivalent, větší než. Může se stát, že hodnota některého veřejného pole nebo funkce se může u ekvivalentních objektů lišit. Pojem „ekvivalent“ je tranzitivní.
  • Silné (lineární) pořadí (menší než, rovno, větší než). Stejné objekty jsou rozlišitelné pouze podle adresy.
class PersonInFamilyStrom { // ... public : std :: operátor částečného_objednávky <=> ( const PersonInFamilyTree & that ) const { if ( this -> is_the_same_person_as ( that )) return limited_ording :: ekvivalent ; if ( this -> is_transitive_child_of ( that )) return partial_ording :: less ; if ( that . is_transitive_child_of ( * this )) return čiastočné_uspořádání :: větší ; return částečné_uspořádání :: neuspořádané ; } };

Název "hvězdná loď" pochází ze staré hry Star Trek - tyto tři postavy znamenaly " Enterprise ".

Verze těla operace hvězdné lodi jednoduše porovnává všechna pole v pořadí deklarací. Operace "rovná se" tělu je také možná , také porovná všechna pole v pořadí deklarace a automaticky deklaruje operaci "nerovná se" [19] . =default=default

Koncepty

Koncept - požadavky na parametry šablony, aby tato šablona dávala smysl. Po většinu životnosti C++ byl koncept popisován slovně, se složitými chybami ve známých a platných záhlavích, jako je STL, pokud programátor do konceptu nezapadal. Pokud programátor napíše šablonu sám, může omylem opustit koncept a neuvidí ho v testovacím programu, protože se zdá, že nejjednodušší typy mají mnoho výchozích funkcí, jako je kopírovací konstruktor, přiřazení a aritmetické operace. int

šablona < classT > _ koncept bool RovnostPorovnatelné ( ) { návrat vyžaduje ( T a , Tb ) { { a == b } -> Boolean ; // Koncept znamenající typ, který se má převést na booleovský { a != b } -> booleovský ; }; }

Řetězcové konstanty jako parametry šablony

Kompilace zpracování řetězců bylo snem C++ již dlouhou dobu a dalším krokem k němu jsou řetězcové konstanty v šablonách [20] . Zejména bych rád převedl regulární výrazy na bytecode již při kompilaci. Experimentální knihovny regulárních výrazů již zaznamenaly až 3000násobné zrychlení ve srovnání s std::regex .

šablona < auto & str > void f () { // str = char const (&)[7] } f < "foobar" > ();

Inicializace pojmenované struktury

Řádná inicializace struktur C je chybná, pokud se očekává expanze struktury nebo pokud může dojít k záměně dvou sousedních prvků. Nový standard přidal , který existoval v C po dlouhou dobu, ale nebyl formalizován v C++ [21] . Point p { 10, 20 };Point p { .x=10, .y=20 };

Navíc vám tato konstrukce umožňuje inicializovat přesně tu možnost union, kterou potřebujete.

union FloatInt { plovák jakoPloat ; int32_t asInt ; }; FloatInt x { . asInt = 42 };

Odstraněno ve srovnání s C:

  • inicializace pojmenovaného pole — počínaje C++11, hranaté závorky na začátku výrazu označují funkci lambda.int arr[3] = {[1] = 5};
  • deklarace mimo provoz  - konflikty s autodestruktory C++: vytvořeno v jednom pořadí, zničeno v jiném?Point p { .y=20, .x=10 };
  • pojmenovaná inicializace členů vnořené struktury  - málo používanéstruct B b = {.a.x = 0};
  • míchání pojmenované a řadové inicializace:Point p {.x = 1, 2};

Změny funkcí lambda

Funkce lambda se objevily v C++11 po jiných programovacích jazycích. Řeší několik problémů najednou: nahrazují preprocesor, pokud je nutné provést stejný kód na dvou místech funkce, a jeho umístění do samostatného objektu / funkce je časově náročné; posuňte text funkce blíže k požadovanému místu; vám umožní psát funkčním stylem. Pojmenováno po lambda kalkulu , jednom ze základů funkcionálního programování.

Explicitní zachycení objektu ve funkci lambda [=, this](){}a [=, *this](){}[22] . Jak bylo uvedeno výše, implicitní odposlech ve funkcích lambda byl zakázán. this

Tradiční syntaxe šablony lambda namísto C++14 . Tato syntaxe je výhodnější, pokud potřebujete provést autotest nebo vypočítat nějaký odvozený typ [23] . [](auto x)

// Bylo auto f = []( auto vector ) { using T = typename decltype ( vector ) :: value_type ; ... }; // Stalo se auto f = [] < typename T > ( std :: vector < T > vector ) { ... };

Funkce lambda v nevyčíslitelných kontextech : podpisy, návratové typy, parametry šablony [24] [25] .

std :: prioritní_fronta < int , // typ prvku std :: vector < int > , // typ kontejneru decltype ( []( int a , int b ) -> bool { // typ funkce porovnání prvků return a > b ; }) > q ;

Aby tento kód fungoval, je potřeba ještě jedna změna – funkce lambda bez háčků má nyní výchozí konstruktor a operátor přiřazení [24] [26] . Všechny instance této pseudotřídy dělají totéž a neexistuje způsob, jak přinutit frontu dané priority k porovnání v jiném pořadí. Konstruktory kopírování a přesunutí byly původně ve všech funkcích lambda.

V seznamu zachycení funkce lambda je nyní možné ponechat operaci expanze proměnné části [24] [27]  - dříve k tomu bylo nutné zahrnout objekt n-tice. Tato šablona například vrací funkci lambda, kterou lze v případě potřeby kdykoli zavolat – volá funkci foo () a již obsahuje kopie všech dat potřebných k volání.

// Byla šablona < class ... Args > auto delay_invoke_foo ( Args ... args ) { return [ tup = std :: make_tuple ( std :: move ( args )...)]() -> decltype ( auto ) { return std :: použít ([]( auto const & ... args ) -> decltype ( auto ) { return foo ( args ...); }, tup ); }; } // Stala se šablonou < class ... Args > auto delay_invoke_foo ( Args ... args ) { return [ args = std :: move ( args )...]() -> decltype ( auto ) { return foo ( args ...); }; }

Redakční změny

Nové implicitní podmínky přesunu

Vyjasněné podmínky, kdy je potřeba implicitně hýbat objektem, zejména při vyvolání výjimek: [28]

void f () { Tx ; _ zkuste { T y ; zkuste { g ( x );} chytit (...) { pokud ( /*...*/ ) hodit x ; // se nepohne - x mimo blok try throw y ; // přesun - y uvnitř bloku try } g ( y ); } catch (...) { g ( x ); // g(y); // chyba } }

Čísla se znaménkem - dvojkový doplněk

Když byl jazyk C v plenkách, existovala „zoo“ různých strojů a vzdělávací stroj MIX , ​​který vynalezl Donald Knuth , to odrážel - bajt mohl uložit 64 až 100 různých hodnot a formát čísel se znaménkem nebyla specifikována. Po více než čtyřicet let se usadili na 8bitovém bajtu a dvojkovém doplňku , především kvůli jednoduchosti a součinnosti , což bylo uvedeno ve standardu [29] .

Aritmetické přetečení v aritmetice bez znaménka je ekvivalentní operacím modulo při aritmetice se znaménkem - nedefinované chování .

Nový model paměti

Ústně ukončeno s C++17 , určeno pro PowerPC a ARM, formalizováno a vráceno k použití. Vyztužené [30] . memory_order_consumememory_order_seq_cst

Knihovna

Drobné změny

  • Nové verze týkající se polí [31] [32] .make_unique/make_shared
  • atomic<shared_ptr<>>a .atomic<weak_ptr<>>
  • atomic_ref<>, objekt, který umožňuje vyrobit cokoliv atomového [33] .
  • std::erase, , zjednodušit metaprogramování [34] .std::erase_if
  • map.contains[35] .
  • Nová hlavička  je standardním místem pro oznámení související s vývojem konkrétní standardní knihovny [36] . Prohlášení jsou implementována.<version>
  • to_address — převod objektu podobného ukazateli na ukazatel [37] . již existuje, ale vyžaduje dereferenci, která se může stát nedefinovaným chováním .addressof
  • Novinka #definepro testování funkčnosti kompilátoru a knihovny [38] . Standardy C++ jsou obrovské a ne všichni vývojáři kompilátorů je rychle začleňují do svých produktů. A některé – C++11 garbage collection – zůstávají útržky dodnes (2021), nejsou implementovány v žádném kompilátoru.
  • Zjednodušené kari pomocí [39] .bind_front
  • source_location - obal pro makra a podobná v C++.__FILE__
  • Nový nadpis s matematickými konstantami [40] . Předtím i obvyklé π a e existovaly pouze jako rozšíření.<numbers>

Deklarace funkce constexpr

  • std::pointer_traits[41] .
  • xxx.empty()a některé další. Psaní se místo toho stalo standardní chybou C++ [42] [43] a je deklarováno .xxx.empty();xxx.clear();[[nodiscard]]
  • <numeric>[44] .
  • konstruktor-destruktory std::vector a std::string , důsledek relaxací constexpr. V době revize (květen 2020) to žádný kompilátor nepodporuje [45] .

Knihovna formátování

printf je příliš nízkoúrovňový, nebezpečný a nerozšiřitelný. Standardní funkce C++ umožňují pouze zřetězení řetězců, a proto jsou pro lokalizaci nepohodlné .

Proto C++20 zavedlo typově bezpečnější mechanismus formátování řetězců založený na Pythonu [46] .

char c = 120 ; auto s1 = std :: formát ( "{:+06d}" , c ); // "+00120" auto s2 = std :: format ( "{:#06x}" , 0xa ); // "0x000a" auto s3 = std :: format ( "{:<06}" , -42 ); // "-42 " (0 je ignorováno kvůli zarovnání <)

Schopnosti:

  • Stejný parametr lze naformátovat libovolněkrát různými způsoby.
  • Střídání je možné vyměnit.
  • Zarovnání vlevo, na střed a vpravo, libovolný znak.
  • Ve výchozím nastavení jsou čísla, data a tak dále formátována lokálně neutrálně; pokud je potřeba lokalizace, nastaví se explicitně.
  • Funguje prostřednictvím šablon, a proto se rozšiřuje na všechny typy.
  • Závorky mohou být vynechány {{ }} .

Nevlastnící ukazatele na pole (rozpětí)

std::string_view se ukázal jako skvělý objekt a udělali to samé pro pole - std::span [47] . Zároveň může span změnit obsah paměti, na rozdíl od string_view .

void do_something ( std :: span < int > p ) { std2 :: řazení ( p ); for ( int & v : p ) { v += p [ 0 ]; } } // ... std :: vector < int > v ; udělat_něco ( v ); intdata [ 1024 ] ; udělat_něco ( data ); boost :: kontejner :: small_vector < int , 32 > sm ; udělat_něco ( sm );

Knihovna pro práci s bity <bit>

  • Počítání počtu bitů
  • Zaokrouhlení na sílu dvou
  • Převod bit-to-bit z jednoho typu na druhý (viz rychlá inverzní odmocnina )
  • Rotate , standardní funkce mnoha procesorů
  • Určení Endianness cílového stroje

Knihovna pro práci se synchronizovanými "výstupními proudy" <syncstream>

Výstupní vlákno zpravidla zpracovává přístup z různých vláken provádění samo . Při vícevláknovém protokolování vyvstává úkol: shromáždit data (například řádek textu) do vyrovnávací paměti dostatečné délky a odeslat je do proudu v jedné operaci.

K tomu se používá jednoduchá třída, která je potomkem . ostream

osyncstream { cout } << "Odpověď je " << 6 * 7 << endl ;

Veškerý výstup do podřízeného vlákna se odehrává v jediné operaci v destruktoru.

Knihovna rozsahů <rozsahy>

Komplexní knihovna se používá tam, kde je potřeba jednotný přístup, jako je std::vector a std::deque [48] .

Knihovna kalendářů a časových pásem v <chrono>

Komplexní knihovna pro kalendářní výpočty [49] .

auto d1 = 2018_y / mar / 27 ; _ auto d2 = 27_d / březen / 2018 ; _ auto d3 = březen / 27 / 2018 ; rok_měsíc_den dnes = podlaha < dny > ( system_clock :: now ()); tvrdit ( d1 == d2 ); tvrdit ( d2 == d3 ); tvrdit ( d3 == dnes );

Písmeno j znamená join  – to znamená, že když je objekt vlákna zničen, systém čeká na dokončení úlohy.

Kromě toho můžete pomocí knihovny požádat o zastavení vlákna. stop_token

#include <vlákno> #include <iostream> pomocí jmenného prostoru std :: literals :: chrono_literals ; void f ( std :: stop_token stop_token , int hodnota ) { while ( ! stop_token . stop_requested ()) { std :: cout << hodnota ++ << ' ' << std :: flush ; std :: this_thread :: sleep_for ( 200ms ) ; } std :: cout << std :: endl ; } int main () { std :: jvlákno vlákno ( f , 5 ); // vytiskne 5 6 7 8... po dobu přibližně 3 sekund std :: this_thread :: sleep_for ( 3 s ); // Destruktor jthread volá request_stop() a join(). }

Svodidla a šrouby

Bariéra je mezivláknový synchronizační mechanismus, který funguje takto: jakmile se n vláken shromáždí u bariéry , provede funkční objekt a uvolní je. Obvykle se používá pro pravidelnou koordinaci částečně paralelizovaných úloh: poté, co vlákna dokončí svůj podíl, koordinátor spustí a rozhodne, co dál.

Západka je zjednodušená jednorázová závora [50] .

Heterogenní vyhledávání v unordered_set / map

Hlavní účel: klíče úložiště jsou „těžké“ objekty (například string ), ale jako vyhledávací klíč jsou přijatelné i lehké: string_view a dokonce const char*. Je implementován velmi jednoduše: je přidána šablonová funkce find, která akceptuje jakýkoli typ, zatímco samotné heterogenní vyhledávání je zahrnuto typem markeru [51] . Jsou podporovány čtyři funkce: find, count, equal_range, include. C++23 očekává více funkcí, které podporují heterogenní vyhledávání, jako je mazání [52] . is_transparent

Pro samovyvažovací vyhledávací stromy ( set / map ) implementované v C++14.

Tato funkce není ve výchozím nastavení povolena kvůli chybě: převod typu nemusí zachovat vztahy, na kterých kontejner pracuje. Například , ale . Hledání zlomkového čísla v tedy nepovede k tomu, co potřebujete [53] . Takže programátor sám musí povolit ty alternativní klíče, které se jistě hodí. 1.0 < 1.1static_cast<int>(1.0) == static_cast<int>(1.1)set<int>

struct string_hash { pomocí is_transparent = void ; [[ nodiscard ]] operátor size_t ()( const char * txt ) const { return std :: hash < std :: string_view > {}( txt ); } [[ nodiscard ]] operátor size_t ()( std :: string_view txt ) const { return std :: hash < std :: string_view > {}( txt ); } [[ nodiscard ]] operátor size_t ()( const std :: string & txt ) const { return std :: hash < std :: string > {}( txt ); } }; std :: unordered_map < std :: string , int , string_hash , std :: equal_to <>> m { { "Ahoj Super dlouhý řetězec" , 1 }, { "Další dlouhý řetězec" , 2 }, { "Toto nemůže spadat do Vyrovnávací paměť jednotného přihlášení" , 3 } }; bool nalezen = m . obsahuje ( "Ahoj Super dlouhý řetězec" ); std :: cout << "Nalezeno: " << std :: boolalpha << nalezeno << '\n' ;

Implementováno jako experimentální knihovny

  • Concurrency v2 [54] , včetně bloků úloh. Verze 1 je součástí C++17.
  • Odraz v1 [55]
  • Síť v1 [56]

Zanecháno pro budoucnost

  • Smlouvy – existuje konkurenční nabídka
  • Metatřídy
  • Účinkující
  • Vlastnosti
  • Prodloužená budoucnost

Viz také

Poznámky

  1. ISO/IEC 14882:2020  (anglicky) . ISO . Staženo: 21. prosince 2020.
  2. ↑ Aktuální stav : Standardní C++  . Získáno 8. února 2019. Archivováno z originálu dne 8. září 2020.
  3. P1152R4: Ukončení podporyvolatile . Získáno 9. srpna 2022. Archivováno z originálu dne 9. srpna 2022.
  4. Zavržení pozůstatkových knihovních částí v C++17 . Získáno 29. ledna 2021. Archivováno z originálu 13. září 2017.
  5. Ukončení podpory <codecvt> . Získáno 29. ledna 2021. Archivováno z originálu 16. září 2017.
  6. Navrhované rozlišení pro CA 14 (shared_ptr use_count/unique) . Získáno 29. ledna 2021. Archivováno z originálu dne 7. července 2017.
  7. P1161R3: Odmítněte použití operátoru čárka ve  výrazech pro indexování . www.open-std.org . Získáno 21. prosince 2020. Archivováno z originálu dne 9. listopadu 2020.
  8. Zpráva z cesty: Podzimní schůze ISO C++ standardů (Albuquerque) – Sutter's Mill . Staženo 8. února 2019. Archivováno z originálu 13. února 2019.
  9. Moduly (od C++20) - cppreference.com . Získáno 2. února 2021. Archivováno z originálu dne 27. ledna 2021.
  10. Coroutines (C++20) - cppreference.com . Získáno 3. února 2021. Archivováno z originálu dne 25. března 2021.
  11. Pryč s typename! . Získáno 13. srpna 2020. Archivováno z originálu dne 22. dubna 2018.
  12. Archivovaná kopie . Získáno 14. srpna 2020. Archivováno z originálu dne 15. srpna 2020.
  13. Povolení volání virtuálních funkcí v konstantních výrazech . www.open-std.org . Získáno 11. března 2019. Archivováno z originálu 11. června 2018.
  14. P1330R0 - Změna aktivního člena unie uvnitř constexpr . Získáno 13. srpna 2020. Archivováno z originálu dne 26. července 2019.
  15. P1002R0 - Try-catch bloky ve funkcích constexpr . Získáno 8. února 2019. Archivováno z originálu 11. listopadu 2018.
  16. P1327R0 – Povolení dynamického_castu, polymorfního typeid v konstantních výrazech . Získáno 13. srpna 2020. Archivováno z originálu dne 26. července 2019.
  17. ↑ Více kontejnerů constexpr  . www.open-std.org . Staženo 21. prosince 2020. Archivováno z originálu dne 14. listopadu 2020.
  18. Podmíněně explicitní konstruktory C++20 | Blog týmu C++ . Získáno 2. února 2021. Archivováno z originálu dne 23. ledna 2021.
  19. Výchozí porovnání (od C++20) - cppreference.com . Získáno 7. ledna 2022. Archivováno z originálu dne 7. ledna 2022.
  20. Řetězcové literály jako netypové parametry šablony . Archivováno z originálu 11. prosince 2017.
  21. Tim Shen, Richard Smith. P0329R4: Určené  znění inicializace . http://www.open-std.org/ . Staženo 21. prosince 2020. Archivováno z originálu dne 15. listopadu 2020.
  22. Thomas Köppe. Povolit zachycení lambda [=, toto ] . Staženo 8. února 2019. Archivováno z originálu 9. února 2019.
  23. Známá syntaxe šablony pro generické  lambdy . Získáno 8. února 2019. Archivováno z originálu dne 21. listopadu 2018.
  24. ↑ 1 2 3 Zpráva z cesty: C++ Standards Meeting v Albuquerque, listopad 2017  , je tu Waldo!  (20. listopadu 2017). Archivováno z originálu 11. prosince 2017. Staženo 8. února 2019.
  25. Formulace pro lambdy v neohodnocených kontextech . Archivováno z originálu 12. prosince 2017.
  26. Výchozí sestavitelné a přiřaditelné bezstavové lambdy . Archivováno z originálu 12. prosince 2017.
  27. Rozšíření balíčku v lambda init-capture . www.open-std.org . Staženo 11. prosince 2017. Archivováno z originálu 14. února 2020.
  28. Archivovaná kopie . Získáno 14. srpna 2020. Archivováno z originálu dne 12. srpna 2020.
  29. P1236R0: Alternativní znění pro P0907R4 Celá čísla se znaménkem jsou doplňkem dvou . Archivováno z originálu 11. listopadu 2018.
  30. P0668R4: Revize modelu paměti C++ . Archivováno z originálu 11. listopadu 2018.
  31. std::make_unique, std::make_unique_for_overwrite - cppreference.com . Získáno 29. ledna 2021. Archivováno z originálu dne 3. února 2021.
  32. std::make_shared, std::make_shared_for_overwrite - cppreference.com . Získáno 29. ledna 2021. Archivováno z originálu dne 3. února 2021.
  33. std::atomic_ref - cppreference.com . Získáno 2. března 2021. Archivováno z originálu dne 27. dubna 2021.
  34. Přijměte konzistentní vymazávání kontejnerů z Library Fundamentals 2 pro C++20 . Získáno 2. února 2021. Archivováno z originálu dne 8. března 2021.
  35. std::map<Key,T,Compare,Alocator>::contains - cppreference.com . Získáno 2. února 2021. Archivováno z originálu 11. června 2018.
  36. Archivovaná kopie . Získáno 2. února 2021. Archivováno z originálu dne 20. ledna 2021.
  37. Nástroj pro převod ukazatele na surový ukazatel . Získáno 2. února 2021. Archivováno z originálu dne 20. února 2018.
  38. Integrace maker pro testování funkcí do C++ WD . Získáno 8. února 2019. Archivováno z originálu dne 20. července 2018.
  39. Zjednodušená aplikace dílčích funkcí . Získáno 2. února 2021. Archivováno z originálu dne 28. září 2020.
  40. Standardní záhlaví knihovny <čísla> - cppreference.com . Získáno 2. března 2021. Archivováno z originálu dne 25. ledna 2021.
  41. P1006R1 - Constexpr v std::pointer_traits . Získáno 8. února 2019. Archivováno z originálu 11. listopadu 2018.
  42. string::empty - Reference C++ . Získáno 29. ledna 2021. Archivováno z originálu dne 28. října 2020.
  43. 100 chyb v projektech Open Source C/C . Získáno 29. ledna 2021. Archivováno z originálu dne 26. ledna 2021.
  44. Knihovna čísel - cppreference.com . Získáno 2. února 2021. Archivováno z originálu dne 21. dubna 2021.
  45. C++20: The Unspoken Features – Human Readable Magazine . Získáno 8. prosince 2020. Archivováno z originálu dne 30. listopadu 2020.
  46. Knihovna formátování (C++20) - cppreference.com . Získáno 29. ledna 2021. Archivováno z originálu dne 31. ledna 2021.
  47. Standardní záhlaví knihovny  - cppreference.com . Získáno 29. ledna 2021. Archivováno z originálu dne 27. dubna 2021.
  48. Knihovna rozsahů (C++20) - cppreference.com . Získáno 3. února 2021. Archivováno z originálu dne 16. ledna 2021.
  49. Rozšíření <chrono> na kalendáře a časová pásma . Získáno 3. února 2021. Archivováno z originálu 13. května 2018.
  50. P0342R0: Časové bariéry . Získáno 8. února 2019. Archivováno z originálu dne 24. listopadu 2019.
  51. std::unordered_set<Key,Hash,KeyEqual,Allocator>::find - cppreference.com . Získáno 31. května 2022. Archivováno z originálu dne 31. května 2022.
  52. C++20: Heterogenní vyhledávání v (ne)uspořádaných kontejnerech – příběhy C++ . Získáno 17. května 2022. Archivováno z originálu dne 24. května 2022.
  53. slanění / Tip týdne #144: Heterogenní vyhledávání v asociativních kontejnerech . Získáno 17. května 2022. Archivováno z originálu dne 18. května 2022.
  54. C++ Extensions for Parallelism Version 2 .
  55. C++ Extensions for Reflection .
  56. C++ Extensions for Networking .