C++23
C++23 je očekávaným standardem pro programovací jazyk C++ .
Zakázáno a odstraněno
Odebráno
- Garbage collection (C++11) - ve skutečnosti to nikdo nepodporoval.
- Přidán pseudo -konstruktor - jako nápověda: je zakázáno vytvářet řetězec z nulového ukazatele.string(nullptr_t) = delete
Zakázáno
- aligned_storage, (C++11) - jsou chybné, je obtížné je spojovat do větších struktur. Náhrada je [1] .aligned_unionalignas
Zákaz zrušen
- Operace , , s -variables (zakázané v C++20) — mikrokontroléry často používají vícebitové porty mapované do paměti [2] . Hledání v knihovnách mikrokontrolérů takové využití pro operace nenašlo , zůstaly zakázané.&=|=^=volatile±=
Jazyk
Drobné změny
- Direktivy preprocesoru #elifdefa #elifndef[3] .
- Předpříkaz if/loop může být alias pomocí: . Fungovalo to v C++20 , protože typedef je syntakticky definice proměnné [4] .for (using T = int; T e : v)for (typedef int T; T e : v)
- Kód povolen - auto nyní umožňuje ukazatele a odkazy na pole [5] .int a[3]; auto (*p)[3] = &a;
- Nová doslovná přípona (ekvivalent znaménka ), ( ).123zsize_t123uzsize_t
- Ve funkci lambda bez parametrů je přijatelné vynechat závorky, pokud existuje klíčové slovo a další podobné: [6] .mutable[s2 = std::move(s2)] mutable {}
- Opakování atributů je povoleno [7] – ukázalo se, že je často generují makra.
- Implicitní převod z int→bool na , , a [8] je povolen . Ale: pokud je tento int roven něčemu jinému než 0 a 1 - chyba. Zlomková čísla, ukazatele a další předměty jsou zakázány.static_assertif constexprexplicit(bool)noexcept(bool)explicit/noexcept
- Typ návratu ocasu v lambda funkcích se nejprve podívá do háčků a teprve potom do okolního textu [9] :auto counter1 = [j=0]() mutable -> decltype(j) { return j++; };
- Atributy jsou povoleny pro funkce lambda [10] :auto lm = [][[nodiscard, vendor::attr]]()->int { return 42; };
- Když se konstruktor dědí, dědí se také vodítka dedukcí [11] .
if consteval
Dřívější , vytvořená jako vestavěná funkce kompilátoru, se ukázala jako chybná [12] . Například:
std::is_constant_evaluated()
constexpr size_t strlen ( char const * s ) {
//if constexpr (std::is_constant_evaluated()) { Bylo, nevolalo verzi assembleru
if consteval { // Stalo se pro ( const char * p = s ; ; ++ p ) {
if ( * p == '\0' ) {
return static_cast < std :: size_t > ( p - s );
}
} } jinak {
__asm__ ( "Něco optimalizovaného pro SSE" );
}
}
Kompilátory samozřejmě vydávají varování, ale není zřejmé, co dělat je správné , jinak optimalizovaná verze assembleru vůbec nepoběží.
if (std::is_constant_evaluated())
Druhým důvodem je interakce mezi a .
constexprconsteval
consteval int f ( int i ) { return i ; }
constexpr int g ( int i ) {
// if (std::is_constant_evaluated()) { Bylo, nezkompilováno
if consteval { // Nyní return f ( i ) + 1 ;
} jinak {
návrat 42 ;
}
}
Tento kód se vůbec nezkompiloval – odtud nemůžete volat funkci consteval.
Složené závorky v tehdejší části jsou povinné, ale v jiné části je lze vynechat. Zdá se nemožné psát. Stará funkce není zakázána - extrémně vzácná, ale nezbytná.
if (consteval && n < 0) {
auto(x) je dočasná kopie objektu
Snadný způsob, jak získat objekt jako dočasný, jako [12] :
void pop_front_alike ( Container auto & x ) {
std :: erase ( x.begin ( ), x.end ( ) , auto ( x.front ( ) ) ) ;
}
x.front() - chyba: v závislosti na kontejneru se tato reference podívá buď na jiný objekt, nebo do prázdné paměti.
Níže uvedený kód je správný, ale auditor může být v pokušení chybně odstranit proměnnou .
a
auto a = x . přední ();
std :: erase ( x.begin ( ), x. end ( ) , a ) ;
V programování šablon může být obtížné získat tento typ:
pomocí T = std :: decay_t < decltype ( x . front ()) > ;
std :: erase ( x.begin ( ), x.end ( ) , T ( x.front ( ) ) ) ;
Název byl vynechán ze dvou důvodů: prvalue je vysoce technický koncept a nevhodné chování pro pole (ukáže ukazatel).
prvalue_cast
Operace vícerozměrného indexování (hranaté závorky)
Stávající metody [13] :
pole ( 1 , 2 , 3 , 4 , 5 ) = 42 ; // vypadá hrozně pole [{ 1 , 2 , 3 , 4 , 5 }] = 42 ; // velmi nesrozumitelné a nepříjemné psát pole [ 1 ][ 2 ][ 3 ][ 4 ][ 5 ] = 42 ; // trochu lepší, ale pod kapotou to prostě leze
Zatím pouze pro vlastní typy [14] .
int buffer [ 2 * 3 * 4 ] = { };
auto s = mdspan < int , rozsahy < 2 , 3 , 4 >> ( buffer );
s [ 1 , 1 , 1 ] = 42 ;
Různé knihovny implementují chybějící syntaxi různými způsoby, ale v žádném případě to není kompatibilní se syntaxí standardních polí a ztěžuje automatické hledání chyb a vkládání (nasazení funkce přímo do volajícího kódu).
Předmětem diskuse zůstává: je to nutné pro standardní pole; zda zmírnit požadavky a umožnit to mimo třídu.
operator[]
Toto-možnosti
Jedna z vlastností C++ - const-correctness - vede k duplikaci kódu nebo zápisu metod delegování. Je navrženo řešení pomocí šablon [15]
///// WAS /////
class TextBlock {
veřejnost :
char const & operator []( size_t position ) const {
// ...
return text [ pozice ];
}
znak a operátor []( pozice size_t ) {
return const_cast < char &> (
static_cast < TextBlock const &>
( toto )[ pozice ]
);
}
// ...
};
///// STÁT SE /////
class TextBlock {
veřejnost :
šablona < typenameSelf > _
auto & operator []( this Self && self , size_t position ) {
// ...
return self . text [ pozice ];
}
// ...
};
Metody rozšíření zatím nejsou nabízeny, ale v budoucnu budou možné.
Snížené požadavky na constexpr
Seznam odpustků je dlouhý a souvisí se dvěma věcmi:
- Nyní constexpr znamená, že při kompilaci je možná alespoň jedna cesta provedení.
- Knihovny vždy zaostávají za jazykem.
Nyní je tedy možné napsat funkci constexpr, kterou lze bez sady argumentů provést při kompilaci [16] .
Ve funkcích constexpr jsou také povoleny goto , proměnné neliterálních typů, statické/vnitrovláknové proměnné. Pokud je některý z těchto řádků předán během kompilace, funkce je vyhodnocena při provádění. zvýšen na 202103L [17] .
__cpp_constexpr
Statický operátor()
Odebere jednu strojovou instrukci, pokud třída nemá žádná data a vkládání selže [18] . Například v samovyvažovacím stromu s nestandardním pořadím (bylo v C++03 ) a heterogenním vyhledávání ( C++14 ) je možný následující kód:
struct CustomCompare {
pomocí is_transparent = int ; // heterogenní hledání statický bool operátor () ( std :: string_view a , std :: string_view b ) // byl const, stal se statickým { return someCustomLess ( a , b ); }
};
std :: set < std :: string , CustomCompare > things ;
Kódování znaků
Povolené znaky v identifikátorech
Znaky ze sad Unicode XID_Start (start) a XID_Continue (ostatní)
jsou nyní povoleny v identifikátorech .
- Jsou povolena písmena a číslice z různých abeced, včetně čínských znaků , klínového písma a latinsko-arabských matematických písmen, z nichž mnohé jsou znaky podobné písmenům.
- Znaky typu "písmeno/modifikátor" jsou povoleny - 02C6 ˆ "modifier-cap" je povoleno a 02DA ˚ "upper circle" je typu "znak/modifikátor" a je zakázáno.
- Kombinování značek je povoleno, včetně selektorů stylu.
- Emoji , neabecední znaky ze strojírenství a matematiky, formátovací znaky (neviditelné znaky odpovědné za zpracování textu, včetně ZWJ a ZWNJ) jsou zakázány .
Identifikátor musí být normalizován podle algoritmu „kanonického složení“ (NFC, rozložit monolitické znaky na komponenty a znovu sestavit). Pokud ne, program je nesprávný.
Tato změna pouze činí podporu Unicode konzistentnější, ale nijak neřeší problémy s útoky prostřednictvím zdánlivě identických řetězců [19] . Metody předávání takových znaků linkeru závisí na implementaci.
Víceznakové a nezakódované literály wchar_t nejsou povoleny
Různé kompilátory fungovaly odlišně na (facepalm emoji ) na dvoubajtovém wchar_t (Windows), . Obojí je nyní zakázáno [20] .
L'\U0001F926'L'ab'
Víceznakové char literály stále fungují, jsou typu int. Kolik znaků je povoleno a jak budou shromážděny do jednoho čísla, je určeno implementací.
Pojmy "kódování překladu", "kódování výkonu"
Je legální, že jeden může být odlišný od druhého [21] a je jednotkou širokého, implementačně specifického kódování výkonu [22] .
wchar_t
UTF-8 jako multiplatformní překladové kódování musí být bezpodmínečně podporováno všemi kompilátory [23] . Značka pořadí bajtů je ignorována, pokud není v konfliktu s příznaky kompilátoru. Pokud je soubor rozpoznán jako UTF-8, neměl by obsahovat nesprávné kombinace kódů – mohou však existovat správné kombinace odpovídající znakům, které ještě neexistují.
Číselné hodnoty znakových literálů v preprocesoru odpovídají kódování provádění
Dříve to bylo až na implementaci, ale ukázalo se, že hlavním účelem této funkce je určit kódování provádění [24] . Například kód z SQLite :
/* Zkontrolujte, zda stroj používá EBCDIC.
(Ano, věřte tomu nebo ne, stále existují stroje používající EBCDIC.) */
#if 'A' == '\301'
# definovat SQLITE_EBCDIC 1 #else
#
definovat SQLITE_ASCII 1
#endif
Všechny hlavní kompilátory skutečně fungují tímto způsobem.
Je opět povoleno inicializovat pole char a unsigned char pomocí literálu UTF-8
Všechny tři řádky jsou přerušeny v C++20, práce opět v C++23 [25] .
const char * a = u8 "a" ;
const char b [] = u8 "b" ;
const unsigned char c [] = u8 "c" ;
Jak se ukázalo, takové přerušení zkomplikovalo funkce constexpru a narušilo kompatibilitu s C.
Nové screencapy
"\u{1F926}"pro bod v kódu Unicode, pro osmičkovou a pro šestnáctkovou [26] .
"\o{123}""\x{AB}"
Prolomení takových štítů ( ) je zakázáno.
"\x{4" "2}"
"\N{LATIN CAPITAL LETTER A WITH MACRON}"umožňuje odkazovat na symbol jeho názvem unicode [27] .
Redakční změny
- Zřetězení zpětného lomítka nyní povoluje mezery za zpětným lomítkem [28] . Takto fungovaly GCC, Clang a ICC - a MSVC zanechalo mezeru.
- Překladač nesmí přeskupovat pole jednoho objektu, pokud mají nenulovou délku a různá přístupová práva [29] . Takto jednali MSVC, GCC, Clang.
- Zřetězení řetězců s konfliktními předponami kódování jako . Z hlavních kompilátorů to podporuje pouze SDCC - přebírá první z prefixů [30] .L"" u""
- Legalizovaná směrnice #warningpodporovaná všemi [31] .
- Zjednodušená implicitní pravidla přesunu při návratu z funkce [32] .
- Refaktorované rozšířené celočíselné typy specifické pro dodavatele [33] .
- Vyjasněn stav hlavičkových souborů C: jsou nyní pro zpětnou kompatibilitu. Soubor, který nesmí být současně platným souborem C, je nesmí obsahovat [34] .
Harmonizace s C
- Štítek bez operátoru povolen: [35] .{ goto a; ++x; a: }
- Podpora . Neexistuje žádný analog [36] .<stdatomic.h><cstdatomic>
- Je opět povoleno inicializovat pole char a unsigned char pomocí literálu UTF-8 (popsáno výše).
Knihovna
Drobné změny
- exchangeobdržel podmíněný noexcept - pokud je objekt vytvořen tahem a přiřazen kopií bez vyvolání výjimek [37] .
- Heterogenní a v asociativních nádobách [38] . Například klíč úložiště je a přístupový klíč je .extracterasestringstring_view
- string[_view].contains - často potřebujete zkontrolovat přítomnost podřetězce, aniž byste zjistili, kde je shoda [39] .
- Nová funkce , která plněji využívá vlastnosti mechanismu alokace paměti [40] . Postupně do něj budou migrovat kontejnery s proměnnou velikostí.Allocator.allocate_at_least
- Rodina konstant – například pro sledování migrace knihovny ze staré do nové [41] .is_scoped_enumenumenum class
- Funkce pro převod , která je svým názvem srozumitelnější a méně náchylná k chybám [42] .to_underlyingenum → int
- Funkce v záhlaví pro změnu pořadí bajtů v číslech [43] .byteswap<bit>
- iostream nyní může tisknout nestálé ukazatele, stejně jako normální ukazatele [44] .
std::move_only_function
std::functionse stal jednou z "nejtěžších" částí knihovny STL. Zbavením se několika vlastností - nelze kopírovat, chybějící pole a - můžete získat mnohem lehčí objekt [45] . A tento objekt samozřejmě umí pracovat s nekopírovatelnými háčky.
targettarget_type
Monad operace na std::volitelné
Monáda je standardní funkcí funkčních jazyků pro provádění sekvence akcí.
V matematice se posloupnost funkcí zapisuje jako , což není vždy vhodné - v programování něco jako .
x.f().g().h()
std::optional je poměrně jednoduchý wrapper, jehož smyslem je uložit objekt nebo nic. Kontroly „nic“ zabírají velkou část práce s volitelným – ale co když na něm v procesu transformace není žádná kočka? Ale co když není místo, kam nakreslit mašli? [46]
std :: volitelné < obrázek > get_cute_cat ( const image & img ) {
return crop_to_cat ( img ) // obrázek → volitelné; [nullopt] na obrázku není žádná kočka . and_then ( add_bow_tie ) // obrázek → volitelné; [nullopt] nikde přidat luk . and_then ( make_eyes_sparkle ) // obrázek → volitelné; [nullopt] nevidí oči . transform ( make_smaller ) // obrázek → obrázek . transformovat ( add_rainbow ); // obrázek → obrázek }
string::resize_and_overwrite
Používá se pro extrémní optimalizaci na křižovatce řetězců a nízkoúrovňových API:
int komprimovat ( void * out , size_t * out_size , const void * in , size_t in_size );
std :: string CompressWrapper ( std :: string_view input ) {
std :: řetězec komprimovaný ;
komprimovaný . resize_and_overwrite ( input . size (), [ input ]( char * buf , std :: size_t n ) noexcept {
std :: velikost_t komprimovaná_velikost = n ;
auto is_ok = komprimovat ( buf , & komprimovaná_velikost , vstupní . data (), vstupní . velikost ());
tvrdit ( is_ok );
return komprimovaná_velikost ;
});
návrat komprimovaný ;
}
Nabízí se otázka: co bylo optimalizováno ve srovnání s těmito dvěma ? [13] Faktem je, že náklady na alokaci paměti příliš nezávisí na délce vyrovnávací paměti a ve většině případů bude do vyrovnávací paměti alokováno mnohem více paměti, než je skutečně potřeba pro komprimovaný řetězec. Nová funkce neinicializuje vyrovnávací paměť a vynulování velmi dlouhé části paměti - .
resizememset( compressed.data(), compressed.size(), '\0')
spanstream - náhrada za zakázané v C++98 strstream
Existoval strstream - datový tok běžící na poli omezené délky. Zakázán v C++98, byl navržen další podobný mechanismus.
char output [ 30 ]{};
ospanstream os { span < char > { output }};
os << 10 << 20 << 30 ;
auto const sp = os . rozpětí ();
ASSERT_EQUAL ( 6 , sp . velikost ());
ASSERT_EQUAL ( "102030" , std :: řetězec ( sp . data (), sp . velikost ()));
ASSERT_EQUAL ( static_cast < void *> ( výstup ), sp . data ()); // žádné kopírování dat ASSERT_EQUAL ( "102030" , výstup ); // zaručeně ukončeno null
tisk
Zpočátku to bylo:std::cout << std::format("Hello, {}! You have {} mails", username, email_count);
To…
- Prodlužuje binární kód - streamy jsou ze své podstaty těžké.
- Žádná podpora Unicode.
- Vypadá to ošklivě.
K dispozici je lehčí [47] .
std::print("Привет, {}! У вас {} писем", username, email_count);
Volitelné zlomkové typy
název |
Kousky mantisy |
bitové pořadí |
Poznámka
|
float16_t |
10 + |
5 |
Vyhovuje IEEE binary16
|
bfloat16_t |
7 + implicitní 1 |
osm |
Horní dva bajty IEEE binary32 (≈float), používané v knihovnách AI, odtud název brain float
|
float32_t |
23 + implicitní 1 |
osm |
Vyhovuje IEEE binárním32, většině plovoucích implementací
|
float64_t |
52 + implicitní 1 |
jedenáct |
Vyhovuje IEEE binary64, většina implementací double
|
float128_t |
112 + implicitní 1 |
patnáct |
Vyhovuje IEEE binary128
|
Matematické funkce musí mít obaly pro všechny podporované typy - zatímco skutečný výpočet lze provést ve více či méně přesném typu [48] .
Poznámky
- ↑ Zdroj . Získáno 8. srpna 2022. Archivováno z originálu dne 18. července 2022. (neurčitý)
- ↑ https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2327r1.pdf
- ↑ Zdroj . Získáno 20. července 2022. Archivováno z originálu dne 10. června 2022. (neurčitý)
- ↑ P2360R0: Rozšiřte příkaz init tak, aby umožňoval deklaraci aliasu
- ↑ Vydání CWG 2397
- ↑ P1102R2: Pryč s ()! . Získáno 9. srpna 2022. Archivováno z originálu dne 9. srpna 2022. (neurčitý)
- ↑ Zdroj . Získáno 27. července 2022. Archivováno z originálu dne 24. května 2022. (neurčitý)
- ↑ Zúžení kontextových konverzí na bool . Získáno 27. července 2022. Archivováno z originálu dne 27. července 2022. (neurčitý)
- ↑ Změnit rozsah lambda trailing-return-type . Získáno 27. července 2022. Archivováno z originálu dne 27. července 2022. (neurčitý)
- ↑ Zdroj . Získáno 27. července 2022. Archivováno z originálu dne 22. srpna 2022. (neurčitý)
- ↑ Zdroj . Získáno 1. srpna 2022. Archivováno z originálu dne 30. července 2022. (neurčitý)
- ↑ 1 2 `jestliže consteval` . Získáno 20. července 2022. Archivováno z originálu dne 20. července 2022. (neurčitý)
- ↑ 1 2 C++23 - funkce zmrazení zavřít / Sudo Null IT News Získáno 28. července 2022. Archivováno z originálu dne 14. května 2022. (neurčitý)
- ↑ Zdroj . Získáno 20. července 2022. Archivováno z originálu dne 24. května 2022. (neurčitý)
- ↑ Odvození tohoto . Získáno 27. července 2022. Archivováno z originálu dne 12. července 2022. (neurčitý)
- ↑ Uvolnění některých constexpr omezení . Získáno 29. července 2022. Archivováno z originálu dne 25. července 2022. (neurčitý)
- ↑ Nedoslovné proměnné (a štítky a gotos) ve funkcích constexpr . Získáno 20. července 2022. Archivováno z originálu dne 24. května 2022. (neurčitý)
- ↑ statický operátor() . Získáno 29. července 2022. Archivováno z originálu dne 29. července 2022. (neurčitý)
- ↑ Syntaxe identifikátoru C++ využívající standard Unicode, příloha 31 . Získáno 27. července 2022. Archivováno z originálu dne 12. července 2022. (neurčitý)
- ↑ Zdroj . Získáno 27. července 2022. Archivováno z originálu dne 27. července 2022. (neurčitý)
- ↑ P2314R3: Znakové sady a kódování . Získáno 27. července 2022. Archivováno z originálu dne 24. května 2022. (neurčitý)
- ↑ https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2460r2.pdf
- ↑ https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2295r6.pdf
- ↑ Zdroj . Získáno 27. července 2022. Archivováno z originálu dne 24. května 2022. (neurčitý)
- ↑ D2513R3: Oprava kompatibility a přenositelnosti char8_t
- ↑ Zdroj . Získáno 29. července 2022. Archivováno z originálu dne 24. května 2022. (neurčitý)
- ↑ Pojmenované univerzální znaky escape . Získáno 29. července 2022. Archivováno z originálu dne 29. července 2022. (neurčitý)
- ↑ Zdroj . Získáno 27. července 2022. Archivováno z originálu dne 24. května 2022. (neurčitý)
- ↑ Zdroj . Získáno 27. července 2022. Archivováno z originálu dne 24. května 2022. (neurčitý)
- ↑ P2201R1: Smíšené řetězcové doslovné zřetězení . Získáno 27. července 2022. Archivováno z originálu dne 27. července 2022. (neurčitý)
- ↑ Zdroj . Získáno 27. července 2022. Archivováno z originálu dne 30. července 2022. (neurčitý)
- ↑ P2266R3: Jednodušší implicitní tah . Získáno 1. srpna 2022. Archivováno z originálu dne 24. května 2022. (neurčitý)
- ↑ Vyčištění typů celočíselných tříd
- ↑ Vyjasnění stavu „hlaviček C“
- ↑ Zdroj . Získáno 29. července 2022. Archivováno z originálu dne 17. června 2022. (neurčitý)
- ↑ P0943R6: Podpora atomů C v C . Získáno 8. srpna 2022. Archivováno z originálu dne 8. srpna 2022. (neurčitý)
- ↑ P2401R0: Přidejte podmíněnou specifikaci noexcept do std::exchange . Získáno 28. července 2022. Archivováno z originálu dne 28. července 2022. (neurčitý)
- ↑ P2077R3: Heterogenní přetížení při výmazu pro asociativní kontejnery . Získáno 29. července 2022. Archivováno z originálu dne 24. května 2022. (neurčitý)
- ↑ řetězec obsahuje funkci . Získáno 8. srpna 2022. Archivováno z originálu dne 8. srpna 2022. (neurčitý)
- ↑ P0401R6: Poskytování zpětné vazby velikosti v rozhraní alokátoru . Získáno 8. srpna 2022. Archivováno z originálu dne 20. července 2022. (neurčitý)
- ↑ Zdroj . Získáno 8. srpna 2022. Archivováno z originálu dne 24. května 2022. (neurčitý)
- ↑ P1682R3: std::to_underlying pro výčty . Získáno 8. srpna 2022. Archivováno z originálu dne 8. srpna 2022. (neurčitý)
- ↑ P1272R4: Byteswapping pro zábavu&nuf . Získáno 8. srpna 2022. Archivováno z originálu dne 8. srpna 2022. (neurčitý)
- ↑ P1147R1: Tisk „volatilních“ ukazatelů
- ↑ P0288R9: move_only_function . Získáno 20. července 2022. Archivováno z originálu dne 20. července 2022. (neurčitý)
- ↑ p0798R6: Monadické operace pro std::volitelné . Získáno 20. července 2022. Archivováno z originálu dne 20. července 2022. (neurčitý)
- ↑ P2093R14: Formátovaný výstup . Získáno 29. července 2022. Archivováno z originálu dne 24. července 2022. (neurčitý)
- ↑ P1467R9: Rozšířené typy s plovoucí desetinnou čárkou a standardní názvy . Získáno 29. července 2022. Archivováno z originálu dne 29. července 2022. (neurčitý)
C++ |
---|
|
Zvláštnosti |
|
---|
Některé knihovny |
|
---|
Kompilátory |
|
---|
ovlivnil |
|
---|
|