C++14

C++14  je neoficiální název ISO/IEC JTC1 verze standardu C++ (celý název: " International Standard ISO/IEC 14882:2014(E) Programming Language C++ ") [1] . C++14 lze považovat za malé rozšíření C++11 obsahující převážně opravy chyb a drobná vylepšení. Výbor pro vývoj nových standardů zveřejnil návrh N3690 dne 15. května 2013 [2] . Pracovní návrh N3936 byl zveřejněn 2. března 2014, konečné období hlasování skončilo 15. srpna 2014 a výsledek (jednomyslné schválení) byl oznámen 18. srpna 2014 [3] .

Vzhledem k tomu, že vývoj standardu byl zdlouhavý a rok vydání finální verze nebyl určen, byl při vývoji používán také název „C++1y“, podobně jako se standard C++11 nazýval „C+“. +0x" před jeho vydáním (vydání této verze se očekávalo do roku 2010).

Jazykové vlastnosti popsané níže odpovídají pracovnímu návrhu N3797 . V těchto se mohou vyskytovat drobné rozdíly ve srovnání s konečnou verzí normy .

Změny jazyka

Tato část představuje nové základní jazykové funkce v C++14.

Návratový typ odvození pro funkce

C++11 vám umožňuje odvodit návratový typ pro funkce lambda z návratového typu výrazu. C++14 rozšiřuje tuto schopnost na všechny funkce. Nový standard také popisuje odvození typu pro funkce lambda s jiným tvarem než return expression;[4] .

Aby bylo možné použít automatické odvození typu návratu, musí být funkce deklarována s typem autojako návratovým typem, ale bez koncového specifikátoru návratového typu C++11:

auto DeduceReturnType (); // návratový typ bude definován později.

Pokud je vráceno více výrazů na různých místech v těle funkce, všechny tyto výrazy musí mít společný odvozený typ [5] .

Funkce, které používají auto-inferenci návratového typu, mohou používat dopřednou deklaraci, ale lze je použít až poté, co byly definovány. Tyto definice musí být dostupné ve stejné překladové jednotce, ve které jsou použity.

V takových funkcích je možné použít rekurzi , ale rekurzivní volání musí být provedeno po alespoň jedné návratové hodnotě v této funkci [5] :

auto Correct ( int i ) { if ( i == 1 ) vrátit i ; // int se zobrazí jako návratový typ else návrat Správně ( i -1 ) + i ; // teď můžete volat } autoWrong ( int i ) { _ jestliže ( != 1 ) návrat Špatně ( i -1 ) + i ; // nevhodné místo pro rekurzi. Bez předchozího návratu. jiný vrátit i ; // int se zobrazí jako návratový typ }

Alternativní odvození typu při deklaraci

C++11 přidal dva způsoby, jak odvodit typy. autovám umožnilo vytvářet proměnné s typem založeným na přiřazeném výrazu. decltypeumožňuje určit výsledný typ libovolného výrazu. Odvozené typy se však od decltypesebe autolišily. Konkrétně autovždy odvodí nereferenční typ, jako by byl zpracován std::remove_reference, zatímco auto&&vždy odvodí referenční typ. Výsledkem však decltypemůže být buď referenční typ, nebo nereferenční typ, v závislosti na zpracovávaném výrazu [4] :

int i ; int && f (); auto x3a = i ; // decltype(x3a) - int decltype ( i ) x3d = i ; // decltype(x3d) - int auto x4a = ( i ); // decltype(x4a) - int decltype (( i )) x4d = ( i ); // decltype(x4d) - int& auto x5a = f (); // decltype(x5a) - int decltype ( f ()) x5d = f (); // decltype(x5d) - int&&

C++14 přidal syntaxi decltype(auto). Tato syntaxe vám umožňuje používat pravidla decltypedeklarace auto. Dává to smysl pouze v základním kódu.

Syntaxi decltype(auto)lze také použít k odvození návratových typů zadáním návratového typu funkce decltype(auto)namísto autona místě [5] .

Snížení omezení konstantních výrazů

C++11 zavádí koncept constexpr-functions: funkce, které lze spustit v době kompilace. Hodnoty, které vracejí, lze použít v operacích, které vyžadují konstantní výraz, jako je argument šablony. V C++11 constexprvšak mohou -funkce obsahovat pouze jeden návratový výraz (stejně jako static_assertněkolik dalších deklarací).

V C++14 jsou tato omezení částečně zrušena. constexpr-funkce nyní mohou obsahovat následující prvky [4] :

  • Jakékoli jiné oznámení než:
    • staticnebo thread_localproměnné;
    • deklarace proměnných bez inicializátorů.
  • Podmíněné větve pokyny ifa switch.
  • Všechny instrukce smyčky, včetně těch forpro rozsahy.
  • Výrazy, které mění hodnoty objektů, pokud životnost těchto objektů začala ve funkci constexpr-. To také zahrnuje volání všech const constexprnestatických členských funkcí.

Příkaz gotonení povolen ve funkci constexprC++14.

Omezení volání ne- constexprfunkcí zůstávají v platnosti. Pokud se tedy použije forpro rozsahy, funkce begina endkontejnery musí být přetíženy jako constexpr. Pro vestavěný typ std::initializer_listjsou funkce begin/enddefinovány jako constexpr, lokálně i globálně.

Také v C++11 byly všechny nestatické metody deklarované pomocí constexprimplicitně považovány za const-funkce s ohledem na this. Toto omezení bylo odstraněno; nestatické metody nyní mohou být ne- const[6] . Jak však bylo zmíněno dříve, ne const constexpr-metoda může změnit pole tříd pouze v případě, že životnost tohoto objektu začala během vyhodnocování konstantního výrazu.

Šablony proměnných

V předchozích verzích C++ bylo šablonování omezeno na funkce a třídy. C++14 umožňuje vytvářet proměnné šablony.

šablona < typenameT > _ constexpr Tpi = T ( 3,1415926535897932385 ) ; // Platí obvyklá pravidla specializace: šablona <> constexpr const char * pi < const char *> = "pi" ;

V tomto příkladu je definována šablona proměnné, ke pikteré lze přistupovat za účelem získání hodnoty pi pro různé typy (například 3při čtení typu celého čísla; nejbližší hodnota k float, doublenebo long doublepři čtení jako float, doublenebo long double, v tomto pořadí atd.).

Mezi taková prohlášení a definice patří obvyklá šablonová pravidla, včetně pravidel specializace [7] [8] .

Souhrnná inicializace tříd pomocí inicializátorů polí

C++11 zavedl inicializátory polí tříd, což jsou výrazy, které se vztahují na pole na úrovni třídy, pokud je konstruktor neinicializuje sám. Definice agregací byla změněna tak, aby explicitně vylučovala všechny třídy s inicializátory členů, takže inicializace agregace pro ně nebyla možná.

C++14 toto omezení odstraňuje [4] a umožňuje agregovanou inicializaci tříd pomocí inicializátorů polí. Pokud seznam inicializátorů ve složených závorkách neposkytuje hodnotu pro tento argument, převezme inicializátor pole [9] .

Binární literály

Číselné literály v C++14 mohou být specifikovány v binárním tvaru [4] . Syntaxe používá předpony 0bnebo 0B. Podobná syntaxe se používá také v Javě , Pythonu , Perlu a D.

Oddělovače tisíců

V C++14 můžete pomocí apostrofu libovolně oddělovat bity v numerických literálech [10] . V některých případech to zjednodušuje vnímání velkých číselných konstant v kódu a zlepšuje čitelnost kódu.

auto integer_literal = 1'000'000 ; auto floating_point_literal = 0,000'015'3 ; auto binary_literal = 0b0100'1100'0110 ; auto hloupý_příklad = 1'0'0'000'00 ;

Obecné funkce lambda

V C++11 musely být parametry funkce lambda deklarovány se specifickými typy. C++14 toto omezení odstraňuje a umožňuje deklarovat parametry funkce lambda se specifikátorem typu auto[7] .

auto lambda = []( auto x , auto y ) { return x + y ;};

Odvozování typu pro parametry generických funkcí lambda se řídí pravidly podobnými odvozování typu pro auto-proměnné (ale ne zcela identické). Výše uvedený kód je ekvivalentní následujícímu [11] :

struct unnamed_lambda { šablona < typename T , typename U > automatický operátor ()( T x , U y ) const { return x + y ;} }; auto lambda = nepojmenovana_lambda ();

Zachycení výrazů pro funkce lambda

Funkce lambda C++11 vám umožňují zachytit proměnné deklarované ve vnějším rozsahu předáním odkazem nebo hodnotou. To znamená, že nemůžete zachycovat podle hodnoty proměnné typů, které lze pouze přesouvat (ale ne kopírovat) [12] . C++14 umožňuje zachytit proměnné s libovolnou inicializací výrazu. To umožňuje zachytit proměnné s pohybem hodnoty a deklarovat proměnné s názvy nedeklarovanými ve vyšších rozsazích [7] .

Výrazy jsou zachyceny pomocí inicializátorů:

auto lambda = [ hodnota = 1 ] { návratová hodnota ;};

Funkce lambda lambdavrátí 1, protože valuepro parametr byl spuštěn příslušný inicializátor. Typ zachyceného parametru je odvozen z typu inicializátoru, podobně jako při deklaraci proměnné pomocí specifikátoru auto.

Tuto funkci lze použít k zachycení pohybu pomocí standardní funkce std::move:

auto ptr = make_unique < int > ( 10 ); auto lambda = [ hodnota = std :: move ( ptr )] { return * value ;};

Atribut [[deprecated]]

Atribut deprecatedumožňuje označit entity jako zastaralé. K těmto entitám lze stále přistupovat, ale je vydáno varování při kompilaci. Argumentem deprecatedmůže být řetězcový literál vysvětlující důvod ukončení podpory a/nebo možné nahrazení.

[[ zastaralé ]] intf ( ); [[ zastaralé ( "g() není bezpečné pro vlákna. Použijte h() místo g()" )]] void g ( int & x ); void h ( int & x ); void test () { int a = f (); // upozornění: 'f' je zastaralé g ( a ); // varování: 'g' je zastaralé: g() není bezpečné pro vlákna. Použijte h() místo g() }

Nové funkce ve standardní knihovně

Sdílené mutexy a zámky

C++14 přidává sdílené mutexy a nový typ zámku pro sdílené mutexy [13] [14] .

Heterogenní vyhledávání v asociativních kontejnerech

Standardní knihovna C++ definuje čtyři asociativní třídy kontejnerů. Tyto třídy umožňují uživateli vyhledávat hodnoty na základě hodnoty tohoto typu. Kontejnery map umožňují uživateli zadat klíč a hodnotu, přičemž vyhledá klíč a vrátí hodnotu. Vyhledávání se však vždy provádělo na konkrétním typu klíče, ať už to byl klíč, jako v mapě, nebo samotná hodnota, jako v sadě.

C++14 umožňuje indexování asociativních kontejnerů hodnotou libovolného typu za předpokladu, že existuje přetížený porovnávací operátor, který dokáže porovnat hodnotu tohoto typu s hodnotou typu klíče kontejneru [15] . To umožňuje, aby mapové kontejnery s typem klíče byly indexovány podle typových std::stringvýrazů const char*pomocí přetíženého porovnávacího operátoru operator<.

Aby byla zachována zpětná kompatibilita, jsou heterogenní vyhledávání povolena pouze v případě, že komparátor předaný do asociativního kontejneru takové vyhledávání podporuje. Standardní třídy knihoven std::less(výchozí pro kontejnery sad a map) a std::greaterumožňují heterogenní vyhledávání [16] .

Standardní uživatelsky definované literály

C++11 má syntaxi pro uživatelem definované doslovné přípony, ale žádná z nich není použita ve standardní knihovně. C++14 přidává následující standardní literály [15] :

  • "s" k vytvoření různých std::basic_stringtypů.
  • "h", "min", "s", "ms", "us" a "ns" pro vytvoření odpovídajících časových intervalů std::chrono::duration.
string str = "ahoj světe" s ; chrono :: trvání dur = 60 s ;

Dva literály "s" se navzájem neovlivňují, protože řetězcový literál funguje pouze na řetězcích, zatímco druhý literál funguje pouze na číslech [17] .

Adresování n-tic podle typu

std::tuple, představený v C++11, umožňuje agregovat více typizovaných hodnot, které budou indexovány v době kompilace. C++14 rozšiřuje funkcionalitu n-tic tak, aby umožňovala přístup k prvkům n-tice nejen podle indexu, ale také podle typu [15] . Pokud n-tice obsahuje více než jeden prvek požadovaného typu, výsledkem vyhledávání bude chyba při kompilaci [18] :

tuple < string , string , int > t ( "foo" , "bar" , 7 ); int i = get < int > ( t ); // i == 7 int j = get < 2 > ( t ); // stejně jako předtím: j == 7 string s = get < string > ( t ); // chyba kompilace kvůli nejednoznačnosti

Další změny standardní knihovny

std::make_uniquelze použít stejně jako std::make_sharedu objektů std::unique_ptr[7] .

Pro std::integral_constantpřidané přetížení operator(), které vrací konstantní hodnotu [15] .

Analogicky s globálními funkcemi std::begin/std::endbyly přidány funkce, std::cbegin/std::cendkteré vracejí konstantní iterátory na začátek a konec rozsahu.

Poznámky

  1. ISO/IEC 14882:2014 - Informační technologie - Programovací jazyky ​​ - C++ . ISO (14. ledna 2014). Datum přístupu: 26. ledna 2015. Archivováno z originálu 29. ledna 2017.
  2. Návrh výboru, Standard pro programovací jazyk C++ (PDF). ISO (15. května 2013). Získáno 24. července 2014. Archivováno z originálu dne 21. ledna 2022.
  3. Sutter, Herb (18. srpna 2014), Máme C++14! , < https://isocpp.org/blog/2014/08/we-have-cpp14 > . Získáno 18. srpna 2014. Archivováno 19. srpna 2014 na Wayback Machine 
  4. 1 2 3 4 5 Wong, Michael Pohled ze setkání C++ Standard duben 2013 3. část . C/C++ Cafe (30. dubna 2013). Získáno 14. června 2013. Archivováno z originálu 13. října 2013.
  5. 1 2 3 Merrill, Jason N3638 Odpočet typu návratu pro normální funkce (Revision 5) (17. dubna 2013). Získáno 14. června 2013. Archivováno z originálu 25. srpna 2013.
  6. Smith, Richard N3652 Relaxační omezení funkcí constexpr (18. dubna 2013). Získáno 24. července 2014. Archivováno z originálu 25. srpna 2013.
  7. 1 2 3 4 Sutter, Emblem Trip Report: ISO C++ Spring 2013 Meeting . isocpp.org (20. dubna 2013). Získáno 14. června 2013. Archivováno z originálu 20. srpna 2017.
  8. Dos Reis, Gabriel N3651 Variable Templates (Revision 1) (PDF) (19. dubna 2013). Získáno 24. července 2014. Archivováno z originálu 25. srpna 2013.
  9. Vandevoorde, Daveed; Voutilainen, Ville N3653 Inicializátory a agregáty členů (17. dubna 2013). Získáno 24. července 2014. Archivováno z originálu 25. srpna 2013.
  10. Crowl, Lawrence; Smith, Richard; Snyder, Jeff; Vandevoorde, Daveed N3781 Jednoduchá uvozovka jako oddělovač číslic (25. září 2013). Získáno 15. října 2014. Archivováno z originálu 13. dubna 2014.
  11. Faisal, Vali; Sutter, Herb; Abrahams, Dave N3649 Generic (Polymorphic) Lambda Expressions (Revision 3) (19. dubna 2013). Získáno 24. července 2014. Archivováno z originálu 25. srpna 2013.
  12. Přesun zachycení v Lambda . přetečení zásobníku . Získáno 24. července 2014. Archivováno z originálu 24. ledna 2013.
  13. Wong, Michael Pohled ze setkání C++ Standard duben 2013 3. část . C/C++ Cafe (30. dubna 2013). Získáno 14. června 2013. Archivováno z originálu 13. října 2013.
  14. Howard, Hinnant; Vollmann, Detlef; Boehm, Hans N3659 Sdílené zamykání v C++ (Revize 2) (19. dubna 2013). Získáno 24. července 2014. Archivováno z originálu 19. srpna 2013.
  15. 1 2 3 4 Wong, Michael Pohled ze setkání standardu C++ duben 2013 2. část . C/C++ Cafe (26. dubna 2013). Získáno 14. června 2013. Archivováno z originálu 13. října 2013.
  16. N3657 Přidání heterogenního srovnávacího vyhledávání do asociativních kontejnerů (rev 4) (19. března 2013). Získáno 24. července 2014. Archivováno z originálu 19. srpna 2013.
  17. Peter, Sommerlad N3642 Uživatelsky definované literály pro standardní typy knihoven (část 1 – verze 4) (PDF) (18. dubna 2013). Získáno 24. července 2014. Archivováno z originálu 25. srpna 2013.
  18. Spertus, Mike N3670 Formulace pro adresování n-tic podle typu: Revize 2 (19. dubna 2013). Získáno 24. července 2014. Archivováno z originálu 19. srpna 2013.