C++20

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2022. január 17-én felülvizsgált verziótól ; az ellenőrzések 135 szerkesztést igényelnek .

A C++20 a C++ programozási nyelv ISO /IEC szabványának  neve . A specifikációt 2020 decemberében tették közzé [1] .

A C++ Szabványügyi Bizottság 2017 júliusában kezdte meg a C++20 tervezését [2] . A C++20 a C++17 utódja .

A konstans értékre nőtt . __cplusplus202002L

Kitiltva és eltávolítva

Az illékony műveletek tilosak

A módosító nyilvánvalóan gépfüggő - a berendezéssel való kommunikációhoz. Nem világos tehát, hogy ennek vagy annak a műveletnek mi a szemantikája, és hány memóriaelérés lesz. A szálak közötti szinkronizáláshoz jobb a . volatileatomic

A következő műveletek -változókkal tiltottak [3] : volatile

atomicA betiltottak kompenzálására további funkciókat adtunk hozzá .

Az összesített inicializálás eltávolítva, ha van egyéni konstruktor

A korábbi szabványokban az összesített inicializálás megengedett volt, ha a konstruktor vagy jellel volt megjelölve , ami félrevezette a felhasználókat: az objektum inicializálása a konstruktor megkerülésével történik. defaultdelete

struct X { int a = 0 ; x () = alapértelmezett ; }; X x { 5 }; // C++17: OK // C++20: nincs megfelelő konstruktor az 'X' inicializálásához

A tiltások eltávolítva a C++17-ből

A C++17-ben tiltott ritka szabványos könyvtári funkciók eltávolítva: [4] [5] [6]

  • allocator<void> - nem igényeltnek bizonyult;
  • egyes funkciókat allocator a sablon duplikál allocator_traits;
  • raw_storage_iterator - nem hív meg konstruktorokat, ezért korlátozott az alkalmazási területe;
  • get_temporary_buffer - nyilvánvaló buktatói vannak;
  • is_literal_type - használhatatlan az általános kódhoz;
  • shared_ptr::unique() - a megbízhatatlanság miatt többszálú környezetben; ha valóban szükséged van rá, használd ;use_count
  • result_of - helyébe invoke_result;
  • uncaught_exception() - helyébe uncaught_exceptions.
  • <ccomplex>, <ciso646>, <cstdalign>, <cstdbool>, <ctgmath> — nincs jelentése C++-ban. és mások a C-vel való kompatibilitás miatt maradtak.<complex.h>

A megjegyzést eltávolítottuk a nyelvből , amit a C++11-ben a -ra cseréltek . Ha kompatibilitásra van szükséged a C++03-mal, akkor valami ilyesmit kell írnod throw()noexcept

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

Bal:

  • codecvt - valójában nagyon rosszul működött, szakkönyvtárak igénybevételét szorgalmazta a bizottság.
  • iterator - egyszerűbb a nulláról iterátorokat írni, mint ráépíteni.
  • patakok  – nem világos, mi jár cserébe.char*
  • a "hozzárendelés" művelet implicit létrehozása, ha van másoláskonstruktor és destruktor (és másoláskonstruktor is, ha van hozzárendelés és destruktor) - a könyvtár továbbra is erre a viselkedésre támaszkodik.

Egyéb tiltások a nyelvből

  • Implicit elfogás a lambda függvényekben  - a nem egyértelmű szemantika miatt. Létezik mutatóval történő rögzítéshez és másolással történő rögzítéshez.*this[](){ std::cout << myField; }[this](){ std::cout << myField; }[*this](){ std::cout << myField; }
  • A „vessző” művelet bármely a, b és c indexében a nem nyilvánvaló viselkedésnek és a többdimenziós tömbök új szintaxisának létrehozására irányuló vágynak köszönhető [7] . Ha tényleg szüksége van rá, kérem írjon .a[b,c]a[(b,c)]
  • Implicit konverziók felsorolt ​​típusba - az új csillaghajó működésének kiszámíthatóbb viselkedése érdekében ( , háromértékű összehasonlítás).<=>
  • Két tömb összehasonlítása - az új "csillaghajó" művelet kiszámíthatóbb viselkedéséhez ( , háromjegyű összehasonlítás). Legalább egyet mutatóvá kell alakítani.<=>

Egyéb kitiltások a könyvtárból

  • is_pod- az „ egyszerű adatstruktúra ”  összetett fogalma helyett jobb, ha konkrét típustulajdonságokat használunk: triviálisan felépült, triviálisan megsemmisült stb. Ha nagyon szükséges (például adatátvitelhez a bővítmények között ), akkor -vel egyenértékű .is_trivial && is_standard_layout
  • std::rel_ops Az új Starship hadművelet jobban teljesít.
  • atomi képességek  - nem világos, hogyan kell mutatóval dolgozni, atomosan vagy sem. Célszerűbb típusrendszerrel definiálni, .shared_ptratomic<shared_ptr>
  • string::capacity() - most úgy döntött, hogy nem csökkenti a kapacitást.reserve
  • filesystem::u8path – most más, mint .u8stringstring
  • ATOMIC_FLAG_INIT, atomic_init, ATOMIC_VAR_INIT — most a sablonkonstruktor csinálja meg .atomic

Nyelv

Kisebb változtatások

  • UTF-8 egységeket tartalmazó előjel nélküli char8_t típus hozzáadva .
  • using EnumClass, amely lehetővé teszi, hogy a kulcsfontosságú helyeken kevésbé zsúfolt legyen a kód.
  • További inicializálás az objektum által: [8] . Ha a visszaadott objektum ideiglenes , élettartama meghosszabbodik a teljes ciklusra, de a többi ideiglenes objektumot biztonságosan eltávolítjuk, és ha f() igaz, akkor a jelölés hibás.for (T thing = f(); auto& x : thing.items())items()for (auto& x : f().items())

Modulok

A fordítói direktíva #includeegykor egy kényelmes C-mechanizmus volt, ami valójában egy többplatformos assembler volt, amely az assembler segédprogramokon – a linkeren és a könyvtároson – "parazitált". Ezért a C fordítók egyik fontos jellemzője – az assembler után elsőként jelentek meg új platformokon. Ám a projektek bővülésével az összeállítási idejük négyzetesen megnőtt: nőtt mind a fordítási egységek , mind a hozzájuk kapcsolódó fejlécek száma. A modulmechanizmus a C++11 napjai óta régóta vita tárgya.

A következőképpen lépett be a C++20-ba [9] :

// helloworld.cpp export modul helloworld ; // moduldeklaráció import < iostream > ; // behozatali nyilatkozat export void hello () { // kiviteli nyilatkozat std :: cout << "Hello world! \n " ; }

Korutinok

A korutin  egy speciális verem nélküli függvény, amely szüneteltetheti a végrehajtását egy másik függvény végrehajtása közben [10] . A korutin állapotát a kupacmemória tárolja (kivéve, ha az optimalizálónak sikerült megszabadulnia az allokációtól). Úgy néz ki, mint egy normál függvény, de speciális kulcsszavakat tartalmaz . co_*

feladat <> tcp_echo_server () { char adatok [ 1024 ]; mert (;;) { méret_t n = co_wait socket . async_read_some ( puffer ( adatok )); co_await async_write ( socket , buffer ( data , n )); } }

Fizikailag a korutin egy olyan függvény, amely egy frissen létrehozott ígéret objektumot ad vissza. Minden alkalommal, amikor a felhasználó tesz valamit az ígéret objektummal, a vezérlés átkerül a korutin kódra. Számos szabványos ígéret elérhető a könyvtárban - például lusta értékelést biztosít . lazy<T>

A típusnév redundánsnak van nyilvánítva, ahol csak a típus engedélyezett

A sablonokban egyes helyeken a szó typename(megmagyarázva, hogy  típus és nem függvény) már nem szükséges [11] . Ezek a helyek többek között… Object::Thing

  • gépelés után  -newauto x = new Object::Thing;
  • írja be  –usingusing Thing = Object::Thing;
  • végső visszaküldés típusa ;auto f() -> Object::Thing
  • alapértelmezett típus a sablonbantemplate<class T = Object::Thing> T f();
  • írja be: static_cast , const_cast , reinterpret_cast , dynamic_cast  —auto x = static_cast<Object::Thing>(y);
  • változó/függvény típusa a névtérben (beleértve a globálist is) vagy osztályban —Object::Thing variable;
  • függvény/sablon paraméter típusa, ha van azonosító (kivéve az alapértelmezett paraméterérték kiszámításához kapcsolódó kifejezéseket) —void func(Object::Thing x);
sablon < osztály T > T :: Rf ( ); // OK most, írja be a globális névtér sablonba < class T > void f ( T :: R ); // Típusnévre van szükség, enélkül egy T::R-rel inicializált void változót próbálunk létrehozni template < class T > struct S { használva Ptr = PtrTraits < T >:: Ptr ; // Most OK, írja be a T :: R f ( T :: P p ) használatával { // Most OK, írja be az osztályt return static_cast < T :: R > ( p ); // Most OK, static_cast } auto g () -> S < T *>:: Ptr ; // OK most, végső visszatérési típus }; sablon < típusnév T > void f () { érvénytelen ( * pf )( T :: X ); // OK marad, void* típusú változó T::X inicializálva void g ( T :: X ); // Típusnévre van szükség, enélkül egy T::X-szel inicializált void változót próbálunk létrehozni .

Egy tömb méretének kiszámítása új

A tömb mérete az új operátorban mostantól automatikusan levonásra kerül [12]

double a []{ 1 , 2 , 3 }; // OK marad double * p = new double []{ 1 , 2 , 3 }; // Most oké

Új attribútumok

  • [[no_unique_address]] - az adat nélküli változó nem foglalhat helyet, az adatokkal rendelkező változó „lyukaiban” pedig más változók is tárolhatók. De: az azonos típusú változók soha nem lehetnek ugyanazon a címen.
template < class Allocator > class Tárhely { privát : [[ no_unique_address ]] Allocator alloc ; };
  • [[nodiscard("причина")]] az azonos nevű C++17 attribútum kiterjesztése. Azt jelzi, hogy a függvény visszatérési értékét nem szabad figyelmen kívül hagyni, és kiírja az okot.
osztály XmlReader { // XML adatfolyam típusú olvasó nyilvános : [[ nodiscard ( "Ellenőrizze az eredményt vagy használja a requireTag-et" )]] bool getTag ( const char * name ); void requestTag ( const char * név ) { if ( ! getTag ( név )) throw std :: logic_error ( std :: string ( "requireTag: " ) + név + " nem található" ); } };
  • [[likely]] / [[unlikely]] - jegyezze meg, hogy mely ágak alatt szükséges optimalizálni a programot az elágazás- előrejelző legjobb működéséhez . Ezt a technikát valójában már megvalósították néhány fordítóprogramban, lásd __builtin_expectpéldául a GCC-t.
if ( x > y ) [[ nem valószínű ]] { std :: cout << "Ritkán előfordul" << std :: endl ; } másik [[ valószínű ]] { std :: cout << "Gyakran előfordul" << std :: endl ; }

Extended constexpr

A Constexpr lehetővé teszi:

  • virtuális függvények hívása [13] ;
  • hívja a destruktorokat, aminek szintén kell lennie ;constexpr
  • munka a union[14]-el ;
  • work with  - az elfogó blokk nem csinál semmit, és ebben az összefüggésben kivételt dob, mint korábban, a függvény kiszámítja a végrehajtás során [15] ;try
  • használata és [16] ;dynamic_casttypeid
  • new, bizonyos korlátozásokkal [17] ;
  • asmha nem hívják meg az összeállításkor;
  • inicializálatlan változók.

Elméletileg egy ilyen konstrukció lehetővé teszi például, hogy egy konstans std::vektor egyszerűen a megfelelő std::initializer_list memóriájába mutasson , és egy közönséges, nem állandó dinamikus memóriát foglaljon le.

Meghosszabbított fordítási idejű lambda függvényhívások - például rendezheti az std::tuple .

Kulcsszavak consteval és constinit

A constexpr kódot nem kell meghívni fordításkor, és elég annyit írni , hogy a constexpr lánc megszakad az std::set konstruktornál , és végrehajtáskor megtörténik az inicializálás. Néha ez nem kívánatos - ha a változót a program inicializálása során használják (a C++ jól ismert hátránya - a CPP fájlok ellenőrizetlen inicializálási sorrendje), nagy (például egy nagy táblázat) vagy nehezen kiszámítható (ugyanannak inicializálása). táblázat, amely O (n²)). A programozóknak pedig csak sport érdekük fűződik a kód átviteléhez a fordításhoz. A bizalom növelése érdekében két új kulcsszót használunk: std::set<std::string_view> dic { "alpha", "bravo" };

  • constevalfüggvényekben: megköveteli a függvény végrehajtását a fordításkor. A nem fordítási idejű végrehajtható környezetből származó hívás nem engedélyezett. A kompatibilitási fejlécekben lecserélve a régebbi fordítókra a következővel .constexpr
  • constinitváltozóban: megköveteli a változó kiértékelését a fordítási időben. A régebbi fordítókkal való kompatibilitási fejlécekben üres karakterláncra cserélve.
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 ; // hiba, fordításkor kiszámíthatatlan }

explicit (bool)

A kulcsszó összeírható logikai konstans kifejezéssel: ha igaz, akkor az átalakítás csak explicit módon lehetséges. Leegyszerűsíti a metaprogramozást, felváltja a SFINAE [18] idiómát . explicit

// Was, std::forward kihagyva a rövidség sablonnál < class T > struct Wrapper { sablon < class U , std :: enable_if_t < std :: is_convertible_v < U , T >>* = nullptr > Burkoló ( U const & u ) : t_ ( u ) {} sablon < class U , std :: enable_if_t <! std :: is_konvertálható_v < U , T >>* = nullptr > explicit burkoló ( U const & u ) : t_ ( u ) {} T t_ ; }; // Sablon lett < class T > struct Wrapper { template < class U > explicit ( ! std :: is_convertible_v < U , T > ) Wrapper ( U const & u ) : t_ ( u ) {} T t_ ; };

Három számjegyű összehasonlítás ("csillaghajó")

A művelet lehetővé teszi az objektumok összehasonlítását a három módszer egyikével: <=>

  • Részleges sorrend : kisebb, mint, egyenértékű, nagyobb, mint, összehasonlíthatatlan.
  • Gyenge sorrend : kisebb, mint, egyenértékű, nagyobb, mint. Előfordulhat, hogy egy nyilvános mező vagy függvény értéke eltérhet az egyenértékű objektumoknál. Az "egyenértékű" fogalma tranzitív.
  • Erős (lineáris) sorrend (kisebb, egyenlő, nagyobb). Az egyenlő objektumok csak cím alapján különböztethetők meg.
class PersonInFamilyTree { // ... public : std :: partial_ordering operator <=> ( const PersonInFamilyTree & that ) const { if ( ez -> az_ugyanaz_személy_mint ( ez )) return partial_ordering :: ekvivalens ; if ( this -> is_tranzitive_child of ( that )) return partial_ordering :: less ; if ( ez . is_tranzitív_gyermek_a ( * ez )) return részleges_sorrend :: nagyobb ; return partial_ordering :: rendezetlen ; } };

A "csillaghajó" név egy régi Star Trek játékból származik - ez a három karakter az " Enterprise "-t jelentette.

A csillaghajó-művelet törzsverziója egyszerűen összehasonlítja az összes mezőt deklarációs sorrendben. Az "egyenlő" a törzstel művelet is lehetséges , a deklaráció sorrendjében összehasonlítja az összes mezőt, és automatikusan deklarálja a "nem egyenlő" műveletet [19] . =default=default

Fogalmak

Koncepció - a sablon paramétereire vonatkozó követelmények, hogy ennek a sablonnak értelme legyen. A C++ élettartamának nagy részében a koncepciót szóban írták le, összetett hibákkal az ismert-érvényes fejlécekben, például az STL-ben, ha a programozó nem illett bele a koncepcióba. Ha a programozó maga írja meg a sablont, előfordulhat, hogy véletlenül elhagyja a koncepciót, és nem látja a tesztprogramban, mert a legegyszerűbb típusoknál úgy tűnik , sok alapértelmezett funkció van, mint például a másoláskonstruktor, a hozzárendelés és az aritmetikai műveletek. int

sablon < classT > _ koncepció bool EqualityComparable () { return igényel ( T a , T b ) { { a == b } -> Logikai ; // Fogalom, amely egy logikai értékre konvertálandó típust jelent { a != b } -> Boolean ; }; }

Karakterlánc-állandók mint sablonparaméterek

A karakterlánc-feldolgozás lefordítása régóta C++ álom volt, a következő lépés felé a karakterlánc-konstansok a sablonokban [20] . Különösen a reguláris kifejezéseket szeretném bájtkódra konvertálni már a fordításkor. A kísérleti regex-könyvtárak már akár 3000-szeres gyorsulást tapasztaltak az std::regex -hez képest .

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

Elnevezett struktúra inicializálása

A C struktúrák ordinális inicializálása hibás, ha a struktúra bővülése várható, vagy ha két szomszédos elem összekeverhető. Bekerült az új szabvány , amely C-ben sokáig létezett, de C++-ban nem formalizálták [21] . Point p { 10, 20 };Point p { .x=10, .y=20 };

Ezenkívül ez a konstrukció lehetővé teszi, hogy pontosan a kívánt opciót inicializálja union.

union FloatInt { float asFloat ; int32_t asInt ; }; FloatInt x { . asInt = 42 };

C-hez képest eltávolítva:

  • nevű tömb inicializálása – C++11-től kezdve a kifejezés elején lévő szögletes zárójelek lambda függvényt jelölnek.int arr[3] = {[1] = 5};
  • rendellenes kijelentés  - konfliktusok a C++ autodestructorokkal: az egyik sorrendben felépült, a másikban megsemmisült?Point p { .y=20, .x=10 };
  • beágyazott szerkezeti tagok elnevezett inicializálása  – ritkán használatosstruct B b = {.a.x = 0};
  • név és sorszámú inicializálás keverése:Point p {.x = 1, 2};

Változások a lambda függvényekben

A lambda függvények a C++11 -ben jelentek meg más programozási nyelvek után. Egyszerre több problémát oldanak meg: lecserélik az előfeldolgozót, ha a függvény két helyén ugyanazt a kódot kell végrehajtani, és időigényes külön objektumba/függvénybe tenni; vigye közelebb a függvény szövegét a szükséges helyhez; lehetővé teszi, hogy funkcionális stílusban írjon . A lambda kalkulusról kapta a nevét , amely a funkcionális programozás egyik alapja.

Egy objektum explicit elfogása lambda függvényben [=, this](){}és [=, *this](){}[22] . Mint fentebb említettük, az implicit lehallgatást a lambda-funkciókban betiltották. this

Hagyományos lambda sablon szintaxis a C++14 helyett . Ez a szintaxis kényelmesebb, ha öntesztet kell végeznie, vagy valamilyen származtatott típust kell kiszámítania [23] . [](auto x)

// Automatikus volt f = [ ]( auto vektor ) { using T = típusnév decltype ( vektor ) :: érték_típus ; ... }; // Automatikus lett f = [] < típusnév T > ( std :: vector < T > vector ) { ... };

Lambda-függvények nem kiszámítható környezetben : aláírások, visszatérési típusok, sablonparaméterek [24] [25] .

std :: priority_queue < int , // elemtípus std :: vektor < int > , // tároló típusa decltype ( []( int a , int b ) -> bool { // elem-összehasonlító függvény típusa return a > b ; }) > q ;

Ahhoz, hogy ez a kód működjön, még egy változtatásra van szükség – a horgok nélküli lambda funkciónak most van egy alapértelmezett konstruktora és hozzárendelési operátora [24] [26] . Ennek a pszeudoosztálynak minden példánya ugyanazt csinálja, és nincs mód arra, hogy egy adott prioritású sort más sorrendben összehasonlítsanak. A másolás és áthelyezés konstruktorok eredetileg minden lambda függvényben szerepeltek.

A lambda függvény elfogólistájában most már megtartható a változó rész kiterjesztésének művelete [24] [27]  - korábban ehhez egy tuple objektumot kellett beiktatni. Például ez a sablon egy lambda függvényt ad vissza, amely bármikor meghívható, ha szükséges - meghívja a foo () függvényt, és már tartalmazza a meghíváshoz szükséges összes adat másolatát.

// Sablon volt < class ... Args > auto delay_invoke_foo ( Args ... args ) { return [ tup = std :: make_tuple ( std :: move ( args )...)]() -> decltype ( auto ) { return std :: apply ([]( auto const & ... args ) -> decltype ( auto ) { return foo ( args ...); }, tup ); }; } // Sablon lett < class ... Args > auto delay_invoke_foo ( Args ... args ) { return [ args = std :: move ( args )...]() -> decltype ( auto ) { return foo ( args ...); }; }

Szerkesztői változások

Új implicit áthelyezési feltételek

Tisztázott feltételek, amikor szükség van egy tárgy implicit mozgatására, különösen kivételek dobásakor: [28]

void f () { T x ; próbáld meg { T y ; próbáld meg { g ( x );} elkapni (...) { ha ( /*...*/ ) dobj x ; // nem fog mozogni - x a try blokkon kívül dob y ; // mozgás - y a try blokkon belül } g ( y ); } fogás (...) { g ( x ); // g(y); // hiba } }

Előjeles számok - kettős komplementer

Amikor a C nyelv még gyerekcipőben járt, létezett egy „állatkert” különböző gépekből, és a Donald Knuth által feltalált MIX oktatási gép is ezt tükrözte – egy bájtban 64-100 különböző érték tárolható, és az előjeles számok formátuma is. nem volt megadva. Több mint negyven évig a 8 bites bájton és a kettes komplementer mellett döntöttek , elsősorban az egyszerűség és az átjárhatóság miatt , és ezt a szabvány is feljegyezte [29] .

Az előjel nélküli aritmetikában az aritmetikai túlcsordulás egyenértékű a modulo műveletekkel , előjeles aritmetika - meghatározatlan viselkedés esetén .

Új memóriamodell

Szóban elavult a C++17 -tel, PowerPC-hez és ARM-hez szánták, formalizálták és újra használatba vették. Megerősített [30] . memory_order_consumememory_order_seq_cst

Könyvtár

Kisebb változtatások

  • A tömbökhöz kapcsolódó új verziók [31] [32] .make_unique/make_shared
  • atomic<shared_ptr<>>és .atomic<weak_ptr<>>
  • atomic_ref<>, egy objektum, amely lehetővé teszi bármit atomossá tenni [33] .
  • std::erase, , egyszerűsíti a metaprogramozást [34] .std::erase_if
  • map.contains[35] .
  • Az új fejléc  egy szabványos hely az adott szabványkönyvtár fejlesztésével kapcsolatos közleményekhez [36] . A nyilatkozatok végrehajtása meghatározott.<version>
  • to_address — mutatószerű objektum mutatóvá alakítása [37] . már létezik, de hivatkozást igényel, ami meghatározatlan viselkedéssé válhat .addressof
  • Újdonság #definea fordító- és könyvtárfunkciók tesztelésében [38] . A C++ szabványok hatalmasak, és nem minden fordítófejlesztő gyorsan beépíti őket termékeibe. És néhány - a C++11 szemétszállítás - a mai napig csonkok maradnak (2021), amelyeket egyetlen fordító sem implementált.
  • Egyszerűsített currying a [39] segítségével .bind_front
  • source_location - burkoló makrókhoz és hasonlókhoz C++ nyelven.__FILE__
  • Új cím matematikai állandókkal [40] . Azelőtt a szokásos π és e is csak kiterjesztésként létezett.<numbers>

Függvénydeklaráció constexpr

  • std::pointer_traits[41] .
  • xxx.empty()és néhány másik. Az írás helyett C++ standard hiba lett [42] [43] , és deklarálva van .xxx.empty();xxx.clear();[[nodiscard]]
  • <numeric>[44] .
  • std::vector és std::string konstruktor-destruktorai , a constexpr relaxációk következménye. A felülvizsgálat idején (2020. május) ezt egyetlen fordító sem támogatja [45] .

Formázási könyvtár

A printf túl alacsony szintű, veszélyes és nem bővíthető. A C++ szabványos szolgáltatásai csak a karakterláncok összefűzését teszik lehetővé, ezért kényelmetlenek a lokalizáció szempontjából .

Ezért a C++20 bevezetett egy típusbiztosabb karakterlánc formázási mechanizmust Python alapján [46] .

char c = 120 ; auto s1 = std :: formátum ( "{:+06d}" , c ); // "+00120" auto s2 = std :: formátum ( "{:#06x}" , 0xa ); // "0x000a" auto s3 = std :: formátum ( "{:<06}" , -42 ); // "-42 " (a 0 figyelmen kívül hagyva az igazítás miatt <)

Képességek:

  • Ugyanaz a paraméter tetszőleges számú formázható különböző módon.
  • A helyettesítések cserélhetők.
  • Balra, középre és jobbra igazítás, bármilyen karakter.
  • Alapértelmezés szerint a számok, dátumok és így tovább formázása nyelv- és terület-semleges; ha lokalizációra van szükség, akkor az kifejezetten be van állítva.
  • Sablonokon keresztül működik, ezért minden típusra kiterjed.
  • A zárójelek kihagyhatók {{ }} .

Nem birtokló mutatók egy tömbre (span)

Az std::string_view nagyszerű objektumnak bizonyult, és ugyanezt tették a tömbök esetében is - std::span [47] . Ugyanakkor a span módosíthatja a memória tartalmát, ellentétben a string_view -val .

void do_something ( std :: span < int > p ) { std2 :: rendezés ( p ); for ( int & v : p ) { v += p [ 0 ]; } } // ... std :: vektor < int > v ; csinál_valamit ( v ); intdata [ 1024 ] ; do_something ( adat ); boost :: container :: small_vector < int , 32 > sm ; csinál_valamit ( sm );

Könyvtár a <bit> bitekkel való munkához

Könyvtár a szinkronizált "kimeneti adatfolyamokkal" való munkához <syncstream>

A kimeneti szál általában önállóan kezeli a különböző végrehajtási szálak hozzáférését . A többszálú naplózásnál felmerül a feladat: gyűjtsünk adatokat (például egy szövegsort) egy megfelelő hosszúságú pufferbe, és egy műveletben adjuk ki a folyamba.

Ehhez egy egyszerű osztályt használnak, amely a leszármazottja . ostream

osyncstream { cout } << "A válasz: " << 6 * 7 << endl ;

Minden kimenet a slave szálra egyetlen műveletben történik a destruktorban.

Tartománykönyvtár <tartományok>

Komplex könyvtárat használnak, ahol egységes hozzáférésre van szükség, például std::vector és std::deque [48] .

Naptárak és időzónák könyvtára a <chrono>-ban

Komplex könyvtár naptárszámításokhoz [49] .

auto d1 = 2018_y / március / 27 ; _ auto d2 = 27_d / március / 2018 ; _ auto d3 = 2018. március 27. ; _ _ év_hónap_nap ma = emelet < napok > ( rendszer_óra :: most ()); állít ( d1 == d2 ); állít ( d2 == d3 ); assert ( d3 == ma );

A j betű csatlakozást jelent  – ​​vagyis amikor a szál objektum megsemmisül, a rendszer megvárja a feladat befejezését.

Ezenkívül a könyvtár használatával kérheti a szál leállítását. stop_token

#include <szál> #include <iostream> névtér használata std :: literals :: chrono_literals ; void f ( std :: stop_token stop_token , int érték ) { while ( ! stop_token . stop_requested ()) { std :: cout << érték ++ << ' ' << std :: flush ; std :: this_thread :: sleep_for ( 200ms ) ; } std :: cout << std :: endl ; } int main () { std :: jszál szál ( f , 5 ); // körülbelül 3 másodpercig nyomtat 5 6 7 8... std :: this_thread :: sleep_for ( 3 s ); // A jthread destruktora meghívja a request_stop() és a join() függvényt. }

Sorompók és csavarok

A sorompó egy szálak közötti szinkronizálási mechanizmus, amely így működik: amint n szál összegyűlik a sorompónál , végrehajtja a függvényobjektumot, és felszabadítja azokat. Általában a részlegesen párhuzamos feladatok időszakos koordinálására használják: miután a szálak mindegyike befejezte a megosztását, a koordinátor kirúg, és eldönti, hogy mit tegyen.

A retesz egyszerűsített egyszeri akadály [50] .

Heterogén keresés az unordered_set / map

Fő cél: a tárolókulcsok „nehéz” objektumok (például string ), de a könnyűsúlyúak is elfogadhatók keresési kulcsként: string_view és még const char*. Megvalósítása nagyon egyszerű: egy sablon függvényt adunk hozzá, amely bármilyen típust elfogad, míg magát a heterogén keresést a markertípus tartalmazza [51] . Négy funkció támogatott: find, count, equal_range, include. A C++23 több olyan függvényt vár, amely támogatja a heterogén keresést, mint például az erase [52] . is_transparent

A C++14-ben megvalósított önkiegyensúlyozó keresési fákhoz ( set / map ).

Ez a funkció alapértelmezés szerint nincs engedélyezve egy hiba miatt: előfordulhat, hogy a típuskonverzió nem tartja meg azokat a kapcsolatokat, amelyeken a tároló működik. Például , de . Ezért a törtszám keresése nem vezet ahhoz, amire szüksége van [53] . Tehát magának a programozónak kell engedélyeznie azokat az alternatív kulcsokat, amelyek minden bizonnyal megfelelőek. 1.0 < 1.1static_cast<int>(1.0) == static_cast<int>(1.1)set<int>

struct string_hash { using is_transparent = void ; [[ nodiscard ]] size_t operator ()( const char * txt ) const { return std :: hash < std :: string_view > {}( txt ); } [[ nodiscard ]] size_t operator ()( std :: string_view txt ) const { return std :: hash < std :: string_view > {}( txt ); } [[ nodiscard ]] size_t operator ()( const std :: string & txt ) const { return std :: hash < std :: string > {}( txt ); } }; std :: unordered_map < std :: string , int , string_hash , std :: egyenlő_a <>> m { { "Hello Super Long String" , 1 }, { "Another Longish String" , 2 }, { "Ez nem eshet bele SSO puffer" , 3 } }; bool talált = m . tartalmaz ( "Hello Super Long String" ); std :: cout << "Talált: " << std :: boolalpha << talált << '\n' ;

Kísérleti könyvtárakként valósítva meg

  • Concurrency v2 [54] , beleértve a feladatblokkokat. Az 1-es verziót a C++17 tartalmazza.
  • Reflexió v1 [55]
  • Hálózat v1 [56]

A jövőre hagyva

  • Szerződések – van egy versengő ajánlat
  • Metaosztályok
  • Előadók
  • Tulajdonságok
  • Kiterjesztett jövő

Lásd még

Jegyzetek

  1. ISO/IEC 14882:2020  (angol) . ISO . Letöltve: 2020. december 21.
  2. ↑ Jelenlegi állapot : Standard C++  . Letöltve: 2019. február 8. Az eredetiből archiválva : 2020. szeptember 8.
  3. P1152R4: Elavultvolatile . Letöltve: 2022. augusztus 9. Az eredetiből archiválva : 2022. augusztus 9..
  4. Vestigiális könyvtárrészek elavulása a C++17-ben . Letöltve: 2021. január 29. Az eredetiből archiválva : 2017. szeptember 13.
  5. Elavult <codecvt> . Letöltve: 2021. január 29. Az eredetiből archiválva : 2017. szeptember 16..
  6. Javasolt megoldás a CA 14-hez (shared_ptr use_count/unique) . Letöltve: 2021. január 29. Az eredetiből archiválva : 2017. július 7.
  7. P1161R3: A vessző operátor használatának megszüntetése a feliratkozási  kifejezésekben . www.open-std.org . Letöltve: 2020. december 21. Az eredetiből archiválva : 2020. november 9.
  8. Utazási jelentés: Őszi ISO C++ szabványok teljesítése (Albuquerque) – Sutter's Mill . Letöltve: 2019. február 8. Az eredetiből archiválva : 2019. február 13.
  9. Modulok (C++20 óta) - cppreference.com . Letöltve: 2021. február 2. Az eredetiből archiválva : 2021. január 27.
  10. Korutinok (C++20) - cppreference.com . Letöltve: 2021. február 3. Az eredetiből archiválva : 2021. március 25.
  11. Le a típusnévvel! . Letöltve: 2020. augusztus 13. Az eredetiből archiválva : 2018. április 22.
  12. Archivált másolat . Letöltve: 2020. augusztus 14. Az eredetiből archiválva : 2020. augusztus 15.
  13. Virtuális függvényhívások engedélyezése állandó kifejezésekben . www.open-std.org . Letöltve: 2019. március 11. Az eredetiből archiválva : 2018. június 11.
  14. P1330R0 - A konstexpron belüli unió aktív tagjának megváltoztatása . Letöltve: 2020. augusztus 13. Az eredetiből archiválva : 2019. július 26.
  15. P1002R0 - Próbálja elkapni a blokkokat a constexpr függvényekben . Letöltve: 2019. február 8. Az eredetiből archiválva : 2018. november 11.
  16. P1327R0 – Dynamic_cast, polimorf típusazonosító engedélyezése az állandó kifejezésekben . Letöltve: 2020. augusztus 13. Az eredetiből archiválva : 2019. július 26.
  17. További constexpr  tárolók . www.open-std.org . Letöltve: 2020. december 21. Az eredetiből archiválva : 2020. november 14.
  18. C++20 feltételesen explicit konstruktorai | C++ Team Blog . Letöltve: 2021. február 2. Az eredetiből archiválva : 2021. január 23.
  19. Alapértelmezett összehasonlítások (a C++20 óta) - cppreference.com . Letöltve: 2022. január 7. Az eredetiből archiválva : 2022. január 7..
  20. String literálok, mint nem típusú sablonparaméterek . Az eredetiből archiválva : 2017. december 11.
  21. Tim Shen, Richard Smith. P0329R4: Kijelölt inicializálási  szöveg . http://www.open-std.org/ . Letöltve: 2020. december 21. Az eredetiből archiválva : 2020. november 15.
  22. Thomas Köppe. Lambda-rögzítés engedélyezése [=, ez ] . Letöltve: 2019. február 8. Az eredetiből archiválva : 2019. február 9..
  23. Ismerős sablon szintaxis az általános  lambdákhoz . Letöltve: 2019. február 8. Az eredetiből archiválva : 2018. november 21..
  24. ↑ 1 2 3 Utazási jelentés: C++ Standards Meeting Albuquerque-ben, 2017. november  , Ott van Waldo!  (2017. november 20.). Az eredetiből archiválva : 2017. december 11. Letöltve: 2019. február 8.
  25. A lambdák megfogalmazása kiértékeletlen összefüggésekben . Az eredetiből archiválva: 2017. december 12.
  26. Alapértelmezett konstruálható és hozzárendelhető állapot nélküli lambdák . Az eredetiből archiválva: 2017. december 12.
  27. Pack bővítés lambda init-capture funkcióban . www.open-std.org . Letöltve: 2017. december 11. Az eredetiből archiválva : 2020. február 14.
  28. Archivált másolat . Letöltve: 2020. augusztus 14. Az eredetiből archiválva : 2020. augusztus 12.
  29. P1236R0: A P0907R4 alternatív megfogalmazása Az előjeles egész számok kettős kiegészítés . Az eredetiből archiválva : 2018. november 11.
  30. P0668R4: A C++ memóriamodell felülvizsgálata . Az eredetiből archiválva : 2018. november 11.
  31. std::make_unique, std::make_unique_for_overwrite - cppreference.com . Letöltve: 2021. január 29. Az eredetiből archiválva : 2021. február 3..
  32. std::make_shared, std::make_shared_for_overwrite - cppreference.com . Letöltve: 2021. január 29. Az eredetiből archiválva : 2021. február 3..
  33. std::atomic_ref - cppreference.com . Letöltve: 2021. március 2. Az eredetiből archiválva : 2021. április 27.
  34. Következetes tárolótörlés alkalmazása a Library Fundamentals 2-ből a C++20-hoz . Letöltve: 2021. február 2. Az eredetiből archiválva : 2021. március 8.
  35. std::map<Kulcs,T,Összehasonlítás,Leosztó>::contains - cppreference.com . Letöltve: 2021. február 2. Az eredetiből archiválva : 2018. június 11.
  36. Archivált másolat . Letöltve: 2021. február 2. Az eredetiből archiválva : 2021. január 20.
  37. Segédprogram a mutató nyers mutatóvá alakításához . Letöltve: 2021. február 2. Az eredetiből archiválva : 2018. február 20.
  38. Szolgáltatásteszt makrók integrálása a C++ WD-be . Letöltve: 2019. február 8. Az eredetiből archiválva : 2018. július 20.
  39. Egyszerűsített részfunkciós alkalmazás . Letöltve: 2021. február 2. Az eredetiből archiválva : 2020. szeptember 28.
  40. Szabványos könyvtárfejléc <számok> - cppreference.com . Letöltve: 2021. március 2. Az eredetiből archiválva : 2021. január 25.
  41. P1006R1 - Constexpr in std::pointer_traits . Letöltve: 2019. február 8. Az eredetiből archiválva : 2018. november 11.
  42. string::empty - C++ Referencia . Letöltve: 2021. január 29. Az eredetiből archiválva : 2020. október 28..
  43. 100 hiba a nyílt forráskódú C/C projektekben . Letöltve: 2021. január 29. Az eredetiből archiválva : 2021. január 26.
  44. Numerics library - cppreference.com . Letöltve: 2021. február 2. Az eredetiből archiválva : 2021. április 21.
  45. C++20: The Unspoken Features - Human Readable Magazine . Letöltve: 2020. december 8. Az eredetiből archiválva : 2020. november 30.
  46. Formázási könyvtár (C++20) - cppreference.com . Letöltve: 2021. január 29. Az eredetiből archiválva : 2021. január 31.
  47. Szabványos könyvtárfejléc  - cppreference.com . Letöltve: 2021. január 29. Az eredetiből archiválva : 2021. április 27.
  48. Tartományok könyvtára (C++20) - cppreference.com . Letöltve: 2021. február 3. Az eredetiből archiválva : 2021. január 16.
  49. A <chrono> kiterjesztése naptárra és időzónára . Letöltve: 2021. február 3. Az eredetiből archiválva : 2018. május 13.
  50. P0342R0: Időzítési akadályok . Letöltve: 2019. február 8. Az eredetiből archiválva : 2019. november 24.
  51. std::unordered_set<Key,Hash,KeyEqual,Allocator>::find - cppreference.com . Letöltve: 2022. május 31. Az eredetiből archiválva : 2022. május 31.
  52. C++20: Heterogén keresés (nem)rendezett tárolókban - C++ történetek . Letöltve: 2022. május 17. Az eredetiből archiválva : 2022. május 24.
  53. leereszkedés / A hét tippje #144: Heterogén keresés az asszociatív tárolókban . Letöltve: 2022. május 17. Az eredetiből archiválva : 2022. május 18.
  54. C++ Extensions for Parallelism Version 2 .
  55. C++ kiterjesztések a tükrözéshez .
  56. C++ bővítmények a hálózathoz .