C++20

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 17. tammikuuta 2022 tarkistetusta versiosta . tarkastukset vaativat 135 muokkausta .

C++20  on C++-ohjelmointikielen ISO /IEC-standardin nimi . Eritelmä julkaistiin joulukuussa 2020 [1] .

C++-standardikomitea aloitti C++20:n suunnittelun heinäkuussa 2017 [2] . C++20 on C++17 :n seuraaja .

Vakio on kasvanut arvoon . __cplusplus202002L

Kielletty ja poistettu

Toiminnot haihtuvien kanssa ovat kiellettyjä

Modifioija on ilmeisesti koneriippuvainen - kommunikoimaan laitteen kanssa. Joten ei ole selvää, mikä tämän tai tuon operaation semantiikka on ja kuinka monta muistihakua tulee olemaan. Säikeiden väliseen synkronointiin on parempi käyttää . volatileatomic

Seuraavat toiminnot -muuttujien kanssa ovat kiellettyjä [3] : volatile

atomicLisäominaisuuksia on lisätty kompensoimaan sitä, mikä oli kiellettyä .

Poistettu koostettu alustus, kun on olemassa mukautettu rakentaja

Aiemmissa standardeissa aggregaattialustaminen sallittiin, jos rakentaja oli merkitty tai , mikä vei käyttäjiä harhaan: objekti alustetaan rakentajan ohittaen. defaultdelete

rakenne X { int a = 0 ; x () = oletusarvo ; }; X x { 5 }; // C++17: OK // C++20: ei vastaavaa konstruktoria X:n alustukseen

Poistettu kiellot C++17:stä

Poistettu harvinaiset standardikirjastoominaisuudet, jotka on kielletty C++17:ssä: [4] [5] [6]

  • allocator<void> - osoittautui lunastamatta;
  • jotkin toiminnot allocator ovat päällekkäisiä mallissa allocator_traits;
  • raw_storage_iterator - ei kutsu rakentajia ja siksi sen käyttö on rajoitettua;
  • get_temporary_buffer - siinä on selviä sudenkuoppia;
  • is_literal_type - hyödytön yleiselle koodille;
  • shared_ptr::unique() - epäluotettavuuden vuoksi monisäikeisessä ympäristössä; jos todella tarvitset sitä, käytä ;use_count
  • result_of - korvataan invoke_result;
  • uncaught_exception() - korvattu uncaught_exceptions.
  • <ccomplex>, <ciso646>, <cstdalign>, <cstdbool>, <ctgmath> - ei ole merkitystä C++:ssa. ja muut jätettiin yhteensopivuuden vuoksi C:n kanssa.<complex.h>

Huomautus poistettiin kielestä , joka korvattiin C++11: ssä kielellä . Jos tarvitset yhteensopivuutta C++03:n kanssa, sinun on kirjoitettava jotain vastaavaa throw()noexcept

#if __cplusplus < 201103L #määritä ei paitsi heitto() #endif

Vasen:

  • codecvt - Itse asiassa se toimi erittäin huonosti, valiokunta vaati erikoiskirjastojen käyttöä.
  • iterator - iteraattoreita on helpompi kirjoittaa tyhjästä kuin rakentaa sen päälle.
  • purot  - ei ole selvää, mitä vastineeksi saadaan.char*
  • implisiittisen "assign"-operaation luominen, jos on kopioinnin rakentaja ja tuhoaja (ja myös kopioinnin rakentaja, jos on osoitus ja tuhoaja) - kirjasto luottaa edelleen tähän toimintaan.

Muita kieltoja

  • Implisiittinen sieppaus lambda-funktioissa  - epäselvän semantiikan takia. On olemassa osoittimella kaappaamista ja kopiointia varten.*this[](){ std::cout << myField; }[this](){ std::cout << myField; }[*this](){ std::cout << myField; }
  • "Pilkku"-operaatio indekseissä mille tahansa a, b ja c johtuu ei-ilmeisestä käyttäytymisestä ja halusta luoda uusi syntaksi moniulotteisille taulukoille [7] . Jos todella tarvitset sitä, kirjoita .a[b,c]a[(b,c)]
  • Implisiittiset muunnokset lueteltuun tyyppiin - uuden tähtialuksen toiminnan ennakoitavampaa toimintaa varten ( , kolmen arvon vertailu).<=>
  • Kahden taulukon vertailu - uuden operaation "tähtialus" ennakoitavampaa käyttäytymistä varten ( , kolminumeroinen vertailu). Ainakin yksi on muutettava osoittimeksi.<=>

Muut kirjastokiellot

  • is_pod- monimutkaisen " yksinkertaisen tietorakenteen "  käsitteen sijaan on parempi käyttää tiettyjä tyyppiominaisuuksia: se on triviaalisti rakennettu, triviaalisti tuhottu jne. Jos se on erittäin tarpeellista (esimerkiksi tietojen siirtämiseksi laajennusten välillä ), se on vastaa .is_trivial && is_standard_layout
  • std::rel_ops Uusi Starship-operaatio tekee sen paremmin.
  • atomiset ominaisuudet  - ei ole selvää, kuinka osoittimella työskennellä, atomisesti vai ei. On parempi määritellä se tyyppijärjestelmällä, .shared_ptratomic<shared_ptr>
  • string::capacity() - päätti nyt, että se ei vähennä kapasiteettia.reserve
  • filesystem::u8path - on nyt erilainen kuin .u8stringstring
  • ATOMIC_FLAG_INIT, atomic_init, ATOMIC_VAR_INIT - nyt mallin rakentaja tekee sen .atomic

Kieli

Pienet muutokset

  • Lisätty allekirjoittamaton char8_t-tyyppi, joka voi sisältää UTF-8- yksiköitä .
  • using EnumClass, jonka avulla voit tehdä koodin avainpaikoista vähemmän sotkuiseksi.
  • Lisäalustaminen objektin mukaan: [8] . Jos palautettu objekti on väliaikainen , sen käyttöikää pidennetään koko syklin ajaksi, mutta muut väliaikaiset objektit poistetaan turvallisesti, ja jos f() on tosi, merkintä on virheellinen.for (T thing = f(); auto& x : thing.items())items()for (auto& x : f().items())

Moduulit

Kääntäjädirektiivi #includeoli aikoinaan kätevä C-mekanismi, joka oli itse asiassa cross-platform-asentaja, joka "loisi" assembler-apuohjelmissa - linkkerissä ja kirjastonhoitajassa. Tästä syystä C-kääntäjien tärkeä ominaisuus - ne ilmestyivät ensimmäisinä uusille alustoille assemblerin jälkeen. Mutta projektien laajentuessa niiden kokoamisaika kasvoi neliöllisesti: sekä käännösyksiköiden että niihin liittyvien otsikoiden määrä kasvoi. Moduulimekanismi on ollut pitkään kiistanalainen aihe C++11:n päivistä lähtien.

Se tuli C++20:een seuraavasti [9] :

// helloworld.cpp vientimoduuli helloworld ; // moduulin ilmoitus tuonti < iostream > ; // tuonti-ilmoitus vienti void hello () { // vienti-ilmoitus std :: cout << "Hei maailma! \n " ; }

Korutiinit

Korutiini  on erityinen pinoamaton funktio, joka voi keskeyttää suorituksensa toisen toiminnon suorittaessa [10] . Korutiinin tila tallennetaan keon muistiin (ellei optimoija onnistunut pääsemään eroon allokaatiosta). Näyttää tavalliselta funktiolta, mutta sisältää erityisiä korutiiniavainsanoja . co_*

tehtävä <> tcp_echo_server () { merkkidata [ 1024 ] ; varten (;;) { koko_t n = co_await socket . async_read_some ( puskuri ( data )); co_await async_write ( socket , puskuri ( data , n )); } }

Fyysisesti korutiini on funktio, joka palauttaa juuri luodun lupausobjektin. Aina kun käyttäjä tekee jotain lupausobjektilla, ohjaus siirtyy korutiinikoodiin. Useita vakiolupauksia on saatavilla kirjastossa - esimerkiksi tarjoaa laiska arviointi . lazy<T>

typename on julistettu redundantiksi, jos vain tyyppi on sallittu

Joissakin paikoissa malleissa sanaa typename(joka selittää, että se  on tyyppi eikä funktio) enää tarvita [11] . Näihin paikkoihin kuuluu… Object::Thing

  • kirjoita jälkeen  -newauto x = new Object::Thing;
  • kirjoita  -usingusing Thing = Object::Thing;
  • lopullisen palautuksen tyyppi ;auto f() -> Object::Thing
  • oletustyyppi mallissatemplate<class T = Object::Thing> T f();
  • kirjoita static_cast , const_cast , reinterpret_cast , dynamic_cast  —auto x = static_cast<Object::Thing>(y);
  • muuttujan/funktion tyyppi nimiavaruudessa (mukaan lukien yleinen) tai luokassa —Object::Thing variable;
  • funktion/mallin parametrityyppi, jos tunniste on olemassa (lukuun ottamatta parametrin oletusarvon laskentaan liittyviä lausekkeita) —void func(Object::Thing x);
malli < luokka T > T :: Rf ( ); // OK nyt, kirjoita globaaliin nimiavaruuden malliin < class T > void f ( T :: R ); // Tarvitaan tyyppinimi, ilman sitä yritetään luoda void-muuttuja, joka on alustettu T::R- mallilla < class T > struct S { käyttäen Ptr = PtrTraits < T >:: Ptr ; // Nyt OK, kirjoita käyttämällä T :: R f ( T :: P p ) { // Nyt OK, kirjoita luokka return static_cast < T :: R > ( p ); // Nyt OK, static_cast } auto g () -> S < T *>:: Ptr ; // OK nyt, lopullinen palautustyyppi }; malli < tyypin nimi T > void f () { tyhjä ( * pf )( T :: X ); // Pysyy OK, muuttuja tyyppiä void* alustettu T::X void g ( T :: X ); // Tarvitsen tyypin nimen, ilman sitä se on yritys luoda void-muuttuja, joka on alustettu T::X:llä }

Taulukon koon laskeminen uudessa

Uuden operaattorin taulukon koko vähennetään nyt automaattisesti [12]

double a []{ 1 , 2 , 3 }; // Pysyy OK double * p = uusi double []{ 1 , 2 , 3 }; // Nyt ok

Uudet attribuutit

  • [[no_unique_address]] - muuttuja ilman dataa ei välttämättä vie tilaa, ja muut muuttujat voidaan tallentaa dataa sisältävän muuttujan "aukoihin". Mutta: samantyyppiset muuttujat eivät voi koskaan olla samassa osoitteessa.
malli < luokan allokaattori > luokka Tallennus { yksityinen : [[ no_unique_address ]] Allocator alloc ; };
  • [[nodiscard("причина")]] on samannimisen C++17-attribuutin laajennus. Ilmaisee, että funktion palautusarvoa ei pidä jättää huomiotta, ja tulostaa syyn.
luokka XmlReader { // XML-virran tyypin lukija julkinen : [[ nodiscard ( "Tarkista tulos tai käytä requestTag" )]] bool getTag ( const char * nimi ); void requestTag ( const char * nimi ) { jos ( ! getTag ( nimi )) heittää std :: logic_error ( std :: string ( "requireTag: " ) + nimi + "ei löydy" ); } }; if ( x > y ) [[ epätodennäköistä ]] { std :: cout << "Tapahtuu harvoin" << std :: endl ; } muuten [[ todennäköisesti ]] { std :: cout << "Tapahtuu usein" << std :: endl ; }

Extended constexpr

Constexpr sallii:

  • kutsu virtuaalisia toimintoja [13] ;
  • kutsu tuhoajia, joiden on myös oltava ;constexpr
  • työskennellä union[14] :n kanssa ;
  • work with  - sieppauslohko ei tee mitään, ja poikkeuksen heittäminen tässä yhteydessä, kuten ennenkin, laskee funktion suorituksen aikana [15] ;try
  • käyttö ja [16] ;dynamic_casttypeid
  • new, tietyin rajoituksin [17] ;
  • asmjos sitä ei ole kutsuttu käännöksen yhteydessä;
  • alustamattomia muuttujia.

Teoriassa tällainen rakenne mahdollistaa esimerkiksi sen, että vakio std::vektori yksinkertaisesti osoittaa vastaavan std::initializer_list -luettelon muistiin , ja tavallinen ei-vakio varaa dynaamisen muistin.

Laajennetut käännösajan lambda-funktiokutsut - voit esimerkiksi lajitella std::tuple .

Avainsanat consteval ja constinit

constexpr-koodia ei tarvitse kutsua kääntämisen yhteydessä, ja riittää, että kirjoitetaan niin, että constexpr-ketju katkeaa std::set -konstruktorissa ja alustus tapahtuu suorituksen yhteydessä. Joskus tämä ei ole toivottavaa - jos muuttujaa käytetään ohjelman alustuksen aikana (C++:n tunnettu haittapuoli - CPP-tiedostojen alustusjärjestys hallitsematon), suuri (esimerkiksi suuri taulukko) tai vaikea laskea (saman alustus) taulukko, joka ottaa O (n²)). Ohjelmoijat ovat vain urheilullisesti kiinnostuneita koodin siirtämisestä kokoelmaan. Varmuuden lisäämiseksi käytetään kahta uutta avainsanaa: std::set<std::string_view> dic { "alpha", "bravo" };

  • constevalfunktioissa: edellyttää funktion suorittamista käännettäessä. Kutsu kontekstista, joka ei ole käännösajan suoritettava, ei ole sallittu. Korvattu yhteensopivuusotsikoissa vanhemmilla kääntäjillä, joissa on .constexpr
  • constinitmuuttujassa: edellyttää, että muuttuja arvioidaan käännöshetkellä. Korvattu tyhjällä merkkijonolla yhteensopivuusotsikoissa vanhempien kääntäjien kanssa.
consteval int sqr ( int n ) { paluu n * n ; } const auto res2 = sqr ( 5 ) ; int main () { int n ; std :: cin >> n ; std :: cout << sqr ( n ) << std :: endl ; // virhe, ei lasketa käännettäessä }

eksplisiittinen (bool)

Avainsana voidaan kirjoittaa yhteen loogisen vakiolausekkeen kanssa: jos se on tosi, muunnos on mahdollista vain eksplisiittisesti. Yksinkertaistaa metaohjelmointia, korvaa SFINAE [18] -idiomin . explicit

// Was, std::forward jätetty pois lyhyyden mallista < class T > struct Wrapper { malli < class U , std :: enable_if_t < std :: is_convertible_v < U , T >>* = nullptr > Kääre ( U const & u ) : t_ ( u ) {} malli < luokka U , std :: enable_if_t <! std :: on_muunnettavissa_v < U , T >>* = nullptr > eksplisiittinen kääre ( U const & u ) : t_ ( u ) {} T t_ ; }; // Muuttui malliksi < luokka T > struct Wrapper { malli < class U > explicit ( ! std :: is_convertible_v < U , T > ) Wrapper ( U const & u ) : t_ ( u ) {} T t_ ; };

Kolminumeroinen vertailu ("tähtilaiva")

Toiminnon avulla voit vertailla objekteja jollakin kolmesta menetelmästä: <=>

  • Osittainen järjestys : pienempi kuin, vastaava, suurempi kuin, vertaansa vailla.
  • Heikko järjestys : pienempi kuin, vastaava, suurempi kuin. Saattaa käydä niin, että jonkin julkisen kentän tai funktion arvo voi poiketa vastaavista objekteista. Käsite "vastaava" on transitiivinen.
  • Vahva (lineaarinen) järjestys (pienempi kuin, yhtä suuri, suurempi kuin). Samat objektit voidaan erottaa vain osoitteen perusteella.
Class PersonInFamilyTree { // ... julkinen : std :: partial_ordering -operaattori <=> ( const PersonInFamilyTree & that ) const { if ( tämä -> on_sama_henkilö_kuten ( tuo )) return partial_ordering :: vastaava ; if ( this -> is_transitive_child of ( that )) return partial_ordering :: vähemmän ; if ( that . is_transitive_child_of ( * this )) return partial_ordering :: suurempi ; return partial_ordering :: järjestämätön ; } };

Nimi "tähtilaiva" tulee vanhasta Star Trek -pelistä - nämä kolme hahmoa tarkoittivat " Enterprise ".

Starship-operaation runkoversio vertailee kaikkia kenttiä ilmoitusjärjestyksessä. Operaatio "saa" rungon kanssa on myös mahdollista , se myös vertaa kaikkia kenttiä ilmoitusjärjestyksessä ja ilmoittaa automaattisesti operaation "ei ole yhtä suuri" [19] . =default=default

Käsitteet

Konsepti - mallin parametrien vaatimukset, jotta tämä malli on järkevä. Suurimman osan C++:n elämästä käsitettä on kuvattu sanallisesti, ja monimutkaisia ​​virheitä tunnetuissa kelvollisissa otsikoissa, kuten STL, jos ohjelmoija ei sopinut konseptiin. Jos ohjelmoija kirjoittaa mallin itse, hän voi vahingossa jättää käsitteen eikä näe sitä testiohjelmassa, koska yksinkertaisimmilla tyypeillä näyttää olevan monia oletusfunktioita, kuten kopiointikonstruktori, osoitus ja aritmeettiset toiminnot. int

malli < luokkaT > _ käsite bool EqualityComparable () { return vaatii ( T a , T b ) { { a == b } -> Boolen ; // Käsite, joka tarkoittaa tyyppiä, joka muunnetaan loogisiksi { a != b } -> Boolen ; }; }

Merkkijonovakiot malliparametreina

Merkkijonoprosessoinnin kääntäminen on ollut C++-unelma pitkään, ja seuraava askel kohti sitä on merkkijonovakiot malleissa [20] . Erityisesti haluaisin muuntaa säännölliset lausekkeet tavukoodiksi jo käännösvaiheessa. Kokeellisissa regex-kirjastoissa on jo nähty jopa 3000-kertaisia ​​nopeutuksia std:: regexiin verrattuna .

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

Nimetty rakenteen alustus

C-rakenteiden ordinaalinen alustus on virheellinen, jos rakenteen odotetaan laajentuvan tai jos kaksi vierekkäistä elementtiä voidaan sekoittaa. Uusi standardi lisättiin , joka oli olemassa C:ssä pitkään, mutta jota ei formalisoitu C++:ssa [21] . Point p { 10, 20 };Point p { .x=10, .y=20 };

Lisäksi tämän rakenteen avulla voit alustaa juuri uniontarvitsemasi vaihtoehdon.

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

Poistettu verrattuna C:hen:

  • nimeltään taulukon alustus – alkaen C++11:stä, hakasulkeet lausekkeen alussa tarkoittavat lambda-funktiota.int arr[3] = {[1] = 5};
  • julistus epäkunnossa  - ristiriidassa C++-autodestructoreiden kanssa: rakennettu yhdessä järjestyksessä, tuhottu toisessa?Point p { .y=20, .x=10 };
  • nimetty sisäkkäisten rakenteen jäsenten alustus  - harvoin käytettystruct B b = {.a.x = 0};
  • nimetty ja järjestysjärjestyksen alustus:Point p {.x = 1, 2};

Muutoksia lambda-toimintoihin

Lambda-funktiot ilmestyivät C++11 :een muiden ohjelmointikielten jälkeen. Ne ratkaisevat useita ongelmia kerralla: ne korvaavat esiprosessorin, jos on tarpeen suorittaa sama koodi funktion kahdessa paikassa, ja sen sijoittaminen erilliseen objektiin / toimintoon on aikaa vievää; siirrä funktion tekstiä lähemmäs sitä kohtaa, missä sitä tarvitaan; voit kirjoittaa toiminnallisella tyylillä. Nimetty lambda -laskimen mukaan, joka on yksi toiminnallisen ohjelmoinnin perusteista.

Objektin eksplisiittinen sieppaus lambda-funktiossa [=, this](){}ja [=, *this](){}[22] . Kuten edellä mainittiin, implisiittinen sieppaus lambda-toiminnoissa kiellettiin. this

Perinteinen lambda-mallin syntaksi C++14:n sijaan . Tämä syntaksi on kätevämpi, jos sinun on tehtävä itsetesti tai laskettava jokin johdettu tyyppi [23] . [](auto x)

// Oliko automaattinen f = []( automaattinen vektori ) { käyttäen T = tyyppinimi decltype ( vektori ) :: arvo_tyyppi ; ... }; // Automaattinen f = [] < tyypin nimi T > ( std :: vector < T > vector ) { ... };

Lambdafunktiot ei-laskettavissa yhteyksissä : allekirjoitukset, palautustyypit, malliparametrit [24] [25] .

std :: prioriteettijono < int , // elementtityyppi std :: vektori < int > , // säiliötyyppi decltype ( []( int a , int b ) -> bool { // elementin vertailufunktion tyyppi return a > b ; }) > q ;

Jotta tämä koodi toimisi, tarvitaan vielä yksi muutos - lambda-toiminnolla ilman koukkuja on nyt oletuskonstruktori ja osoitusoperaattori [24] [26] . Kaikki tämän pseudoluokan esiintymät tekevät saman asian, eikä tiettyä prioriteettijonoa voi pakottaa vertaamaan eri järjestyksessä. Kopioi ja siirrä konstruktorit olivat alun perin kaikissa lambda-toiminnoissa.

Lambda-funktion sieppauslistassa on nyt mahdollista säilyttää muuttujan osan laajennusoperaatio [24] [27]  - aiemmin tätä varten piti sisällyttää tuple-olio. Tämä malli palauttaa esimerkiksi lambda-funktion, joka voidaan kutsua milloin tahansa haluttaessa - se kutsuu foo () -funktiota ja sisältää jo kopiot kaikista kutsumiseen tarvittavista tiedoista.

// Oli malli < luokka ... 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 ); }; } // Tuli malli < class ... Args > auto delay_invoke_foo ( Args ... args ) { return [ args = std :: move ( args )...]() -> decltype ( auto ) { return foo ( args ...); }; }

Toimitukselliset muutokset

Uudet implisiittiset siirtoehdot

Selvennetyt ehdot, kun objektia vaaditaan implisiittisesti siirrettäessä, erityisesti heitettäessä poikkeuksia: [28]

void f () { Tx ; _ kokeile { T y ; kokeile { g ( x );} saalis (...) { jos ( /*...*/ ) heittää x ; // ei liiku - x try-lohkon ulkopuolella heittää y ; // siirrä - y try-lohkon sisällä } g ( y ); } saalis (...) { g ( x ); // g(y); // virhe } }

Merkilliset numerot - kahden komplementti

Kun C-kieli oli lapsenkengissään, siellä oli erilaisten koneiden "eläintarha", ja Donald Knuthin keksimä opetuskone MIX heijasti tätä - tavulle mahtui 64-100 eri arvoa ja etumerkittyjen numeroiden muoto. ei ollut määritelty. Yli neljänkymmenen vuoden ajan he asettuivat 8-bittiseen tavuun ja kahden komplementtiin ensisijaisesti yksinkertaisuuden ja yhteentoimivuuden vuoksi , ja tämä mainittiin standardissa [29] .

Aritmeettinen ylivuoto etumerkittömässä aritmetiikassa vastaa modulo-operaatioita etumerkillisessä aritmeettisessa - määrittelemätön käyttäytyminen .

Uusi muistimalli

Suullisesti vanhentunut C++17:llä , tarkoitettu PowerPC:lle ja ARM:lle, virallistettu ja palautettu käyttöön. Vahvistettu [30] . memory_order_consumememory_order_seq_cst

Kirjasto

Pienet muutokset

  • Uudet versiot liittyvät taulukoihin [31] [32] .make_unique/make_shared
  • atomic<shared_ptr<>>ja .atomic<weak_ptr<>>
  • atomic_ref<>, esine, jonka avulla voit tehdä mistä tahansa atomiseksi [33] .
  • std::erase, , yksinkertaistaa metaohjelmointia [34] .std::erase_if
  • map.contains[35] .
  • Uusi otsikko  on vakiopaikka tietyn vakiokirjaston kehittämiseen liittyville ilmoituksille [36] . Julistukset on määritelty täytäntöönpanossa.<version>
  • to_address — osoittimen kaltaisen objektin muuntaminen osoittimeksi [37] . on jo olemassa, mutta se vaatii viittauksen poistamista, mikä voi muuttua määrittelemättömäksi käytökseksi .addressof
  • Uutta #definekääntäjän ja kirjaston toiminnallisuuden testaamisessa [38] . C++-standardit ovat valtavat, eivätkä kaikki kääntäjien kehittäjät ole nopeita sisällyttämään niitä tuotteisiinsa. Ja jotkut - C++11 roskienkeräys - ovat jääneet tähän päivään (2021), joita ei ole toteutettu missään kääntäjässä.
  • Yksinkertaistettu curryus kautta [39] .bind_front
  • source_location - kääre makroille ja vastaaville C++:ssa.__FILE__
  • Uusi nimike matemaattisilla vakioilla [40] . Ennen sitä tavallisetkin π ja e olivat olemassa vain laajennuksina.<numbers>

Funktioilmoitus constexpr

  • std::pointer_traits[41] .
  • xxx.empty()ja jotkut muut. Sen sijaan kirjoittamisesta on tullut C++-standardivirhe [42] [43] , ja se julistetaan .xxx.empty();xxx.clear();[[nodiscard]]
  • <numeric>[44] .
  • std::vektorin ja std::stringin konstruktori-destruktorit , jotka ovat seurausta constexpr-relaksaatioista. Tarkasteluhetkellä (toukokuussa 2020) yksikään kääntäjä ei tue tätä [45] .

Muotoilukirjasto

printf on liian matala, vaarallinen ja ei-laajennettavissa. C++:n vakioominaisuudet sallivat vain merkkijonojen yhdistämisen ja ovat siksi hankalat lokalisoinnissa .

Siksi C++20 esitteli Pythoniin perustuvan tyyppiturvallisemman merkkijonomuotoilumekanismin [ 46] .

char c = 120 ; auto s1 = std :: muoto ( "{:+06d}" , c ); // "+00120" auto s2 = std :: muoto ( "{:#06x}" , 0xa ); // "0x000a" auto s3 = std :: muoto ( "{:<06}" , -42 ); // "-42" (0 ohitetaan tasauksen vuoksi <)

Ominaisuudet:

  • Sama parametri voidaan muotoilla kuinka monta kertaa tahansa eri tavoilla.
  • Vaihtoehdot voidaan vaihtaa.
  • Tasaus vasemmalle, keskelle ja oikealle, mikä tahansa merkki.
  • Oletusarvoisesti numerot, päivämäärät ja niin edelleen muotoillaan maa-asetuksen mukaan neutraalisti. jos lokalisointia tarvitaan, se asetetaan eksplisiittisesti.
  • Toimii mallien kautta ja ulottuu siksi kaikkiin tyyppeihin.
  • Sulkeet voidaan jättää pois {{ }}.

Ei-omistavat osoittimet taulukkoon (span)

std::string_view osoittautui loistavaksi objektiksi, ja he tekivät saman taulukoille - std::span [47] . Samaan aikaan span voi muuttaa muistin sisältöä, toisin kuin string_view .

void do_something ( std :: span < int > p ) { std2 :: lajittele ( p ); for ( int & v : p ) { v += p [ 0 ]; } } // ... std :: vektori < int > v ; tee_jotain ( v ); intdata [ 1024 ] ; do_something ( data ); boost :: kontti :: pieni_vektori < int , 32 > sm ; tee_jotain ( sm );

Kirjasto bittien <bitin> kanssa työskentelemiseen

Kirjasto synkronoitujen "lähtövirtojen" kanssa työskentelemiseen <syncstream>

Lähtösäie käsittelee pääsääntöisesti pääsyn eri suoritussäikeistä yksin . Monisäikeisessä lokikirjauksessa syntyy tehtävä: kerätä tiedot (esimerkiksi tekstirivi) riittävän pitkälle puskuriin ja tulostaa ne streamiin yhdellä toimenpiteellä.

Tätä varten käytetään yksinkertaista luokkaa, joka on luvun jälkeläinen . ostream

osyncstream { cout } << "Vastaus on" << 6 * 7 << endl ;

Kaikki ulostulo orjasäikeeseen tapahtuu yhdessä toimenpiteessä destruktorissa.

Aluekirjasto <alueet>

Monimutkaista kirjastoa käytetään silloin, kun tarvitaan yhtenäistä pääsyä, kuten std::vector ja std::deque [48] .

Kalenterien ja aikavyöhykkeiden kirjasto kohteessa <chrono>

Monimutkainen kirjasto kalenterilaskelmia varten [49] .

automaattinen d1 = 2018_y / maaliskuu / 27 ; _ automaattinen d2 = 27_d / maaliskuu / 2018 ; _ auto d3 = 27. maaliskuuta 2018 ; _ _ vuosi_kuukausi_päivä tänään = kerros < päivää > ( system_clock :: now ()); väittää ( d1 == d2 ); väittää ( d2 == d3 ); väittää ( d3 == tänään );

Kirjain j tarkoittaa join  - eli kun säieobjekti tuhoutuu, järjestelmä odottaa tehtävän valmistumista.

Lisäksi kirjastoa käyttämällä voit pyytää säiettä lopettamaan. stop_token

#sisällytä <ketju> #include <iostream> käyttäen nimiavaruutta std :: literals :: chrono_literals ; void f ( std :: stop_token stop_token , int value ) { while ( ! stop_token . stop_requested ()) { std :: cout << arvo ++ << ' ' << std :: huuhtelu ; std :: this_thread :: sleep_for ( 200ms ) ; } std :: cout << std :: endl ; } int main () { std :: jthread lanka ( f , 5 ); // tulostaa 5 6 7 8... noin 3 sekunnin ajan std :: this_thread :: sleep_for ( 3 s ); // Jsäikeen tuhoaja kutsuu request_stop() ja join(). }

Esteet ja pultit

Este on säikeiden välinen synkronointimekanismi, joka toimii näin: heti kun n säiettä kokoontuu esteeseen , se suorittaa funktioobjektin ja vapauttaa ne. Yleensä käytetään osittain rinnakkaisten tehtävien säännölliseen koordinointiin: kun säikeet ovat suorittaneet osuutensa, koordinaattori laukaisee ja päättää, mitä tehdä seuraavaksi.

Salpa on yksinkertaistettu kertakäyttöinen este [50] .

Heterogeeninen haku unordered_set / map

Päätarkoitus: tallennusavaimet ovat "raskaita" objekteja (esimerkiksi merkkijono ), mutta myös kevyet ovat hyväksyttäviä hakuavaimena: string_view ja jopa const char*. Se toteutetaan hyvin yksinkertaisesti: lisätään mallifunktio Find, joka hyväksyy minkä tahansa tyypin, kun taas heterogeeninen haku sisältyy merkkityyppiin [51] . Neljää toimintoa tuetaan: find, count, equal_range, sisältää. C++23 odottaa lisää toimintoja, jotka tukevat heterogeenista hakua, kuten pyyhkimistä [52] . is_transparent

Itsetasapainottaville hakupuille ( set / map ) toteutettu C++14:ssä.

Tämä ominaisuus ei ole oletuksena käytössä virheen vuoksi: tyyppimuunnos ei välttämättä säilytä suhteita, joissa säilö toimii. Esimerkiksi , mutta . Siksi murtoluvun haku ei johda siihen, mitä tarvitset [53] . Ohjelmoijan on siis itse sallittava ne vaihtoehtoiset avaimet, jotka ovat varmasti sopivia. 1.0 < 1.1static_cast<int>(1.0) == static_cast<int>(1.1)set<int>

struct string_hash { käyttäen is_transparent = void ; [[ nodiscard ]] size_t - operaattori ()( const char * txt ) const { return std :: hash < std :: string_view > {}( txt ); } [[ nodiscard ]] size_t - operaattori ()( std :: string_view txt ) const { return std :: hash < std :: string_view > {}( txt ); } [[ nodiscard ]] size_t - operaattori ()( const std :: string & txt ) const { return std :: hash < std :: merkkijono > {}( txt ); } }; std :: unordered_map < std :: string , int , string_hash , std :: equal_to <>> m { { "Hei Super Long String" , 1 }, { "Toinen pitkä merkkijono" , 2 }, { "Tämä ei voi kuulua SSO-puskuri" , 3 } }; bool löydetty = m . sisältää ( "Hello Super Long String" ); std :: cout << "Löytyi: " << std :: boolalpha << löytyi << '\n' ;

Toteutettu kokeellisina kirjastoina

  • Samanaikaisuus v2 [54] , mukaan lukien tehtävälohkot. Versio 1 sisältyy C++17:ään.
  • Heijastus v1 [55]
  • Verkko v1 [56]

Jätetty tulevaisuuteen

  • Sopimukset - on kilpaileva tarjous
  • Metaluokat
  • Esiintyjät
  • Ominaisuudet
  • Laajennettu tulevaisuus

Katso myös

Muistiinpanot

  1. ISO/IEC 14882:2020  (englanniksi) . ISO . Haettu: 21.12.2020.
  2. ↑ Nykyinen tila : Vakio C++  . Haettu 8. helmikuuta 2019. Arkistoitu alkuperäisestä 8. syyskuuta 2020.
  3. P1152R4: Poistetaan käytöstävolatile . Haettu 9. elokuuta 2022. Arkistoitu alkuperäisestä 9. elokuuta 2022.
  4. Vestigiaalikirjaston osien poistaminen käytöstä C++17:ssä . Haettu 29. tammikuuta 2021. Arkistoitu alkuperäisestä 13. syyskuuta 2017.
  5. Poistetaan käytöstä <codecvt> . Haettu 29. tammikuuta 2021. Arkistoitu alkuperäisestä 16. syyskuuta 2017.
  6. Ehdotettu ratkaisu CA 14:lle (shared_ptr use_count/unique) . Haettu 29. tammikuuta 2021. Arkistoitu alkuperäisestä 7. heinäkuuta 2017.
  7. P1161R3: Poista käytöstä pilkkuoperaattorin käyttö  tilauslausekkeissa . www.open-std.org . Haettu 21. joulukuuta 2020. Arkistoitu alkuperäisestä 9. marraskuuta 2020.
  8. Matkaraportti: Syksyn ISO C++ -standardien kokous (Albuquerque) – Sutter's Mill . Haettu 8. helmikuuta 2019. Arkistoitu alkuperäisestä 13. helmikuuta 2019.
  9. Moduulit (C++20:sta lähtien) - cppreference.com . Haettu 2. helmikuuta 2021. Arkistoitu alkuperäisestä 27. tammikuuta 2021.
  10. Korutiinit (C++20) - cppreference.com . Haettu 3. helmikuuta 2021. Arkistoitu alkuperäisestä 25. maaliskuuta 2021.
  11. Alas tyyppinimi! . Haettu 13. elokuuta 2020. Arkistoitu alkuperäisestä 22. huhtikuuta 2018.
  12. Arkistoitu kopio . Haettu 14. elokuuta 2020. Arkistoitu alkuperäisestä 15. elokuuta 2020.
  13. Virtuaalifunktiokutsujen salliminen vakiolausekkeissa . www.open-std.org . Haettu 11. maaliskuuta 2019. Arkistoitu alkuperäisestä 11. kesäkuuta 2018.
  14. P1330R0 - Unionin aktiivisen jäsenen vaihtaminen constexprin sisällä . Haettu 13. elokuuta 2020. Arkistoitu alkuperäisestä 26. heinäkuuta 2019.
  15. P1002R0 - Yritä siepata lohkoja constexpr-funktioissa . Haettu 8. helmikuuta 2019. Arkistoitu alkuperäisestä 11. marraskuuta 2018.
  16. P1327R0 - dynaamisen_castin, polymorfisen tyyppitunnuksen salliminen vakiolausekkeissa . Haettu 13. elokuuta 2020. Arkistoitu alkuperäisestä 26. heinäkuuta 2019.
  17. Lisää constexpr-  säiliöitä . www.open-std.org . Haettu 21. joulukuuta 2020. Arkistoitu alkuperäisestä 14. marraskuuta 2020.
  18. C++20:n ehdollisesti eksplisiittiset konstruktorit | C++ Team -blogi . Haettu 2. helmikuuta 2021. Arkistoitu alkuperäisestä 23. tammikuuta 2021.
  19. Oletusvertailut (C++20:sta lähtien) - cppreference.com . Haettu 7. tammikuuta 2022. Arkistoitu alkuperäisestä 7. tammikuuta 2022.
  20. Merkkijonoliteraalit ei-tyyppisinä malliparametreina . Arkistoitu alkuperäisestä 11. joulukuuta 2017.
  21. Tim Shen, Richard Smith. P0329R4: Nimetty  alustussanakirja . http://www.open-std.org/ . Haettu 21. joulukuuta 2020. Arkistoitu alkuperäisestä 15. marraskuuta 2020.
  22. Thomas Köppe. Salli lambda-kaappaus [=, tämä ] . Haettu 8. helmikuuta 2019. Arkistoitu alkuperäisestä 9. helmikuuta 2019.
  23. Tuttu  mallisyntaksi yleisille lambda-sanomille . Haettu 8. helmikuuta 2019. Arkistoitu alkuperäisestä 21. marraskuuta 2018.
  24. ↑ 1 2 3 Matkaraportti: C++ Standards Meeting Albuquerquessa, marraskuussa 2017  , There 's Waldo!  (20. marraskuuta 2017). Arkistoitu alkuperäisestä 11. joulukuuta 2017. Haettu 8. helmikuuta 2019.
  25. Lambda-sanat arvioimattomissa yhteyksissä . Arkistoitu alkuperäisestä 12. joulukuuta 2017.
  26. Rakennettavat ja määritettävät oletusarvoiset tilattomat lambdat . Arkistoitu alkuperäisestä 12. joulukuuta 2017.
  27. Pakkauksen laajennus lambda-init-capturessa . www.open-std.org . Haettu 11. joulukuuta 2017. Arkistoitu alkuperäisestä 14. helmikuuta 2020.
  28. Arkistoitu kopio . Haettu 14. elokuuta 2020. Arkistoitu alkuperäisestä 12. elokuuta 2020.
  29. P1236R0: Vaihtoehtoinen sanamuoto P0907R4:lle Allekirjoitetut kokonaisluvut ovat kahden komplementteja . Arkistoitu alkuperäisestä 11. marraskuuta 2018.
  30. P0668R4: C++-muistimallin tarkistaminen . Arkistoitu alkuperäisestä 11. marraskuuta 2018.
  31. std::make_unique, std::make_unique_for_overwrite - cppreference.com . Haettu 29. tammikuuta 2021. Arkistoitu alkuperäisestä 3. helmikuuta 2021.
  32. std::make_shared, std::make_shared_for_overwrite - cppreference.com . Haettu 29. tammikuuta 2021. Arkistoitu alkuperäisestä 3. helmikuuta 2021.
  33. std::atomic_ref - cppreference.com . Haettu 2. maaliskuuta 2021. Arkistoitu alkuperäisestä 27. huhtikuuta 2021.
  34. Ota käyttöön Consistent Container Erasure from Library Fundamentals 2 for C++20 . Haettu 2. helmikuuta 2021. Arkistoitu alkuperäisestä 8. maaliskuuta 2021.
  35. std::kartta<Avain,T,Vertaa,Alokaattori>::sisältää - cppreference.com . Haettu 2. helmikuuta 2021. Arkistoitu alkuperäisestä 11. kesäkuuta 2018.
  36. Arkistoitu kopio . Haettu 2. helmikuuta 2021. Arkistoitu alkuperäisestä 20. tammikuuta 2021.
  37. Apuohjelma osoittimen muuttamiseksi raakaosoittimeksi . Haettu 2. helmikuuta 2021. Arkistoitu alkuperäisestä 20. helmikuuta 2018.
  38. Ominaisuustestimakrojen integrointi C++ WD:hen . Haettu 8. helmikuuta 2019. Arkistoitu alkuperäisestä 20. heinäkuuta 2018.
  39. Yksinkertaistettu osatoimintosovellus . Haettu 2. helmikuuta 2021. Arkistoitu alkuperäisestä 28. syyskuuta 2020.
  40. Tavallinen kirjaston otsikko <numerot> - cppreference.com . Haettu 2. maaliskuuta 2021. Arkistoitu alkuperäisestä 25. tammikuuta 2021.
  41. P1006R1 - Constexpr in std::pointer_traits . Haettu 8. helmikuuta 2019. Arkistoitu alkuperäisestä 11. marraskuuta 2018.
  42. merkkijono::tyhjä - C++-viite . Haettu 29. tammikuuta 2021. Arkistoitu alkuperäisestä 28. lokakuuta 2020.
  43. 100 bugia avoimen lähdekoodin C/C-projekteissa . Haettu 29. tammikuuta 2021. Arkistoitu alkuperäisestä 26. tammikuuta 2021.
  44. Numerics library - cppreference.com . Haettu 2. helmikuuta 2021. Arkistoitu alkuperäisestä 21. huhtikuuta 2021.
  45. C++20: The Unspoken Features - Ihmisille luettava aikakauslehti . Haettu 8. joulukuuta 2020. Arkistoitu alkuperäisestä 30. marraskuuta 2020.
  46. Muotoilukirjasto (C++20) - cppreference.com . Haettu 29. tammikuuta 2021. Arkistoitu alkuperäisestä 31. tammikuuta 2021.
  47. Vakiokirjastootsikko  - cppreference.com . Haettu 29. tammikuuta 2021. Arkistoitu alkuperäisestä 27. huhtikuuta 2021.
  48. Aluekirjasto (C++20) - cppreference.com . Haettu 3. helmikuuta 2021. Arkistoitu alkuperäisestä 16. tammikuuta 2021.
  49. <chrono>:n laajentaminen kalentereihin ja aikavyöhykkeisiin . Haettu 3. helmikuuta 2021. Arkistoitu alkuperäisestä 13. toukokuuta 2018.
  50. P0342R0: Ajoitusesteet . Haettu 8. helmikuuta 2019. Arkistoitu alkuperäisestä 24. marraskuuta 2019.
  51. std::unordered_set<Key,Hash,KeyEqual,Allocator>::find - cppreference.com . Haettu 31. toukokuuta 2022. Arkistoitu alkuperäisestä 31. toukokuuta 2022.
  52. C++20: Heterogeeninen haku (järjestämättömissä) säilöissä - C++ Stories . Haettu 17. toukokuuta 2022. Arkistoitu alkuperäisestä 24. toukokuuta 2022.
  53. laskeutuminen / Viikon vinkki #144: Heterogeeninen haku assosiatiivisissa säiliöissä . Haettu 17. toukokuuta 2022. Arkistoitu alkuperäisestä 18. toukokuuta 2022.
  54. C++ -laajennukset rinnakkaisuudelle, versio 2 .
  55. C++ -laajennukset heijastukseen .
  56. C++ -laajennukset verkkokäyttöön .