1 C++11 Syntaksi Jari-Pekka Voutilainen 13.4.2012
2 Range-for Iteroi säiliön kaikki alkiot for-silmukassa. Säiliöltä vaaditaan begin- ja end-iteraattorit. Pätee kaikille C++11 STL-säiliöille, taulukoille, alustuslistoille, säännöllisten lausekkeiden tuloksille ja kaikille käyttäjän määrittämille tyypeille, jotka toteuttavat begin- ja end-iteraattorit. int array[5] = { 1, 2, 3, 4, 5; for ( int i: array) { std::cout << i << std::endl;
3 Static_assert Käännösaikaiset testit Vrt. assert, joka testattiin ajon aikana. Voidaan toteuttaa eri näkyvyysalueilla. Globaali / nimiavaruus Luokka Funktio static_assert(sizeof(void*)!= sizeof(long), "Pointers and longs are same sizes." );
4 Constexpr Mahdollistaa lausekkeen evaluoinnin vakioksi käännösaikana. constexpr int x = std::numeric_limits<int>::max(); int array[x]; std::cout << sizeof(array)/sizeof(*array) << std::endl; Vrt. vanha, joka kaatuu koska käännösaikana ei tiedetä taulukon kokoa. const int x = std::numeric_limits<int>::max(); int array[x]; std::cout << sizeof(array)/sizeof(*array) << std::endl;
5 Constexpr Constant expressionin käyttäminen funktioissa asettaa rajoituksia Vain yksi return-lause ja pitää palauttaa jotain muuta kuin void. Saa kutsua vain constexpr-funktioita. Saa viitata vain globaaleihin muuttujiin, jotka myös ovat constexpr. Constexpr-funktiota voidaan kutsua ajon aikana, jos funktion parametrit eivät ole vakiota. constexpr factorial (int n) { return n > 0? n * factorial( n - 1 ) : 1; int n; cin >> n; factorial(n) Constexpr-funktiot ja muuttujat ovat vakioita, mutta vakiot eivät ole constexpr.
6 Omat literaalit C++03:ssa on valmiiksi määritettyjä literaaleja 12.5 tulkitaan kääntäjän toimesta doubleksi 12.5f tulkitaan floatiksi C++11 mahdollistaa uusien literaalien määrittämisen OutputType operator "" _suffix(const char *literal_string); OutputType some_variable = 1234_suffix; OutputType operator "" _suffix(unsigned long long); OutputType operator "" _suffix(long double); OutputType some_variable = 1234_suffix; OutputType another_variable = 3.1416_suffix;
7 Luokan jäsenfunktiot Uusia määreitä luokan jäsenfunktioiden määrittelyyn Eksplisiittisesti määritetyt oletustoteutukset. class Widget{ Widget() = default; Eksplisiittisesti poistetut funktiot. Poistettuja funktioita ei voi kutsua eikä niihin voi viitata. Yleisin käyttökohde on kopioinnin esto. class Widget{ Widget(const Widget&) = delete; Widget& operator=(const Widget&) = delete;
8 Luokan jäsenfunktiot Jäsenfunktioiden periyttämiseen uudet override ja final. Override eksplisiittisesti määrittää, että kantaluokan funktio pitää ylikirjoittaa. Jos kantaluokasta ei löydy samaa funktiota, kääntäjä antaa virheen. class Base{ virtual void some_func(float); virtual int another_func(); class Derived{ virtual void some_func(float) override; virtual void another_func() override; Final estää kantaluokan funktion ylikirjoittamisen periytetyssä luokassa. //ok //kääntäjä antaa virheen class Base{ virtual void some_func(float); virtual int another_func() final; class Derived{ virtual void some_func(float) override; virtual int another_func() override; //ok //kääntäjä antaa virheen
9 Rakentajat Delegoidut ja periytetyt rakentajat Delegoidulla rakentajalla voidaan kutsua kantaluokan rakentajia suoraan. class SomeType { int number; private: void Construct(int new_number) { number = new_number; SomeType(int new_number) { Construct(new_number); SomeType() { Construct(42); ; vrt. class SomeType { int number; SomeType(int new_number) : number(new_number) { SomeType() : SomeType(42) { ; Rakentaja, joka delegoi toiselle rakentajalle, ei voi tehdä mitään muuta alustuslistassaan. Delegoivan rakentajan koodilohko ajetaan, kun palataan delegoidusta rakentajasta.
10 Rakentajat Using-sanalla voidaan käyttää kantaluokan rakentajia class Base{ Base(int); class Derived{ using Base::Base; Derived foo(10); // kutsuu kantaluokan rakentajaa Jos periytetty luokka määrittelee samanlaisen rakentajan kuin kantaluokka, kantaluokan rakentajaa ei periytetä. Lopullisen koodin pitää olla laillista. class Base{ private: Base(int); class Derived{ using Base:Base; Derived bar(10); //virhe, kutsuu Derived(int), joka kutsuu Base(int), joka on privaatti. Virhe huomataan oliota luotaessa.
11 Rakentajat Periytetyn luokan jäsenmuuttujat jäävät alustamatta. Ongelmaa voidaan vähentää oletusarvoilla. class base{ Base(int); class Derived{ using Base::Base; private: int x = 0; int y = 0;
12 Using Using-sanan käyttö laajempaa. Template aliaksina: template <typename T> using MyAllocVec = std::vector<t, MyAllocator>; MyAllocVec<int> v; // std::vector<int, MyAllocator> template<std::size_t N> using StringArray = std::array<std::string, N>; StringArray<15> sa; //std::array<std::string, 15> Tyyppi aliaksina typedef std::unordered_set<int> inthash; using inthash = std::unordered_set<int>; typedef void (*CallBackPtr)(int); using CallBackPtr = void(*)(int);
13 Attribuutit Metatietoja kääntäjälle. C++11 määrittelee kaksi attribuuttia: noreturn ja carries_dependency Noreturn kertoo kääntäjälle että funktio, johon attribuutti on liitetty, ei koskaan palaa. [[noreturn]] void somefunction() { throw "error"; Carries_dependency kertoo kääntäjälle, että kyseisen funktion tai parametrin muistinkäyttöä voi optimoida säikeiden välillä. [[carries_dependency]] int *foo(); void bar( [[carries_dependency]] int *f );
14 Eksplisiittiset tyyppimuunnokset C++11 mahdollistaa tyyppimuunnoksen määrittämisen eksplisiittiseksi. struct A { //implisiittinen muunnos int:ksi operator int() { return 100; //eksplisiittinen muunnos string:ksi explicit operator std::string() { return explicit ; ; int main() { A a; int i = a; // ok, implisiittinen muunnos std::string s = a; //error, vaatii eksplisiittisen muunnoksen std::string se = static_cast<std::string>(a); // ok, eksplisiittinen muunnos
15 Inline namespace Inline namespace mahdollistaa versioinnin nimiavaruuden sisällä. Inlinellä merkitty nimiavarauus sisällytetään ylempään nimiavaruuteen. namespace Networking { namespace V1 { class TCPSocket; inline namespace V2 { class TCPSocket; Networking::TCPSocket *t; Networking::V1::TCPSocket *t2; Networking::V2::TCPSocket *t3; using namespace Networking; TCPSocket *t4 V1::TCPSocket *t5 V2::TCPSocket *t6 // Networking::V2::TCPSocket // Networking::V1::TCPSocket // Networking::V2::TCPSocket // Networking::V2::TCPSocket // Networking::V1::TCPSocket // Networking::V2::TCPSocket class UDPSocket; Useampi inline namespace aiheuttaa konflikteja, jos kyseisissä nimiavaruuksissa on saman nimisiä muuttujia.