C++ Rusija: kaip tai atsitiko

Jei pjesės pradžioje sakote, kad ant sienos kabo C++ kodas, tai pabaigoje jis jums šaus į koją.

Bjarne'as Stroustrupas

Spalio 31 – lapkričio 1 dienomis Sankt Peterburge vyko C++ Russia Piter konferencija – viena iš plataus masto programavimo konferencijų Rusijoje, kurią organizavo JUG Ru Group. Kviestiniai pranešėjai yra C++ standartų komiteto nariai, CppCon pranešėjai, O'Reilly knygų autoriai ir tokių projektų kaip LLVM, libc++ ir Boost prižiūrėtojai. Konferencija skirta patyrusiems C++ kūrėjams, norintiems pagilinti savo žinias ir keistis gyvo bendravimo patirtimi. Studentams, magistrantams ir universiteto dėstytojams taikomos labai malonios nuolaidos.

Konferenciją Maskvoje bus galima aplankyti jau kitų metų balandį, o kol kas mūsų studentai papasakos, ką įdomaus sužinojo praėjusiame renginyje. 

C++ Rusija: kaip tai atsitiko

Nuotrauka iš konferencijos albumas

apie mus

Du studentai iš Nacionalinio tyrimų universiteto Aukštosios ekonomikos mokyklos Sankt Peterburge dirbo šį postą:

  • Liza Vasilenko yra 4 kurso bakalauro studentė, studijuojanti programavimo kalbas pagal taikomosios matematikos ir informatikos programą. Pirmaisiais universiteto metais susipažinęs su C++ kalba, vėliau įgijau patirties su ja dirbdamas stažuodamasis šioje pramonės šakoje. Mano aistra programavimo kalboms apskritai ir funkciniam programavimui ypač paliko pėdsaką renkantis pranešimus konferencijoje.
  • Dania Smirnov yra magistrantūros programos „Programavimas ir duomenų analizė“ 1 kurso studentė. Dar mokykloje rašiau olimpiados uždavinius C++, o paskui kažkaip atsitiko taip, kad kalba nuolat iškildavo edukacinėje veikloje ir ilgainiui tapo pagrindine darbo kalba. Nusprendžiau dalyvauti konferencijoje, kad patobulinčiau savo žinias ir sužinočiau apie naujas galimybes.

Naujienlaiškyje fakulteto vadovybė dažnai dalijasi informacija apie edukacinius renginius, susijusius su mūsų specialybe. Rugsėjo mėnesį pamatėme informaciją apie C++ Rusiją ir nusprendėme užsiregistruoti klausytojais. Tai pirma mūsų dalyvavimo tokiose konferencijose patirtis.

Konferencijos struktūra

  • Ataskaitos

Per dvi dienas ekspertai perskaitė 30 pranešimų, apimančių daugybę aktualių temų: išradingas kalbos funkcijų naudojimas sprendžiant taikomąsias problemas, būsimi kalbos atnaujinimai, susiję su naujuoju standartu, C++ dizaino kompromisai ir atsargumo priemonės dirbant su jų pasekmėmis, pavyzdžiai. įdomios projekto architektūros, taip pat kai kurių kalbos infrastruktūros detalių. Vienu metu vyko trys spektakliai, dažniausiai du rusų ir vienas anglų kalba.

  • Diskusijų zonos

Po kalbos visi neužduoti klausimai ir nebaigtos diskusijos buvo perkeltos į specialiai komunikacijai su pranešėjais skirtas zonas, įrengtas žymeklių lentomis. Geras būdas pailsėti tarp kalbų maloniu pokalbiu.

  • Žaibo pokalbiai ir neformalios diskusijos

Jei norite pateikti trumpą pranešimą, galite užsiregistruoti lentoje vakaro žaibo pokalbiui ir gauti penkias minutes laiko pasikalbėti bet kuo konferencijos tema. Pavyzdžiui, greitas įvadas apie C++ skirtus dezinfekavimo priemones (kai kuriems tai buvo nauja) arba pasakojimas apie sinusinės bangos generavimo klaidą, kurią galima tik išgirsti, bet nematyti.

Kitas formatas yra panelinė diskusija „Komitetas iš širdies į širdį“. Scenoje kai kurie standartizacijos komiteto nariai, projektoriuje – židinys (oficialiai - nuoširdžiai atmosferai sukurti, bet juokingesnė atrodo priežastis „nes VISKAS dega“), klausimai apie standartą ir bendrą C++ viziją. , be karštų techninių diskusijų ir holivarų. Paaiškėjo, kad komitete yra ir gyvų žmonių, kurie galbūt kažkuo nėra visiškai tikri arba kažko nežino.

Holivarų gerbėjams liko trečiasis renginys – BOF sesija „Go vs. C++“. Mes priimame Go mylėtoją, C++ mėgėją, prieš sesijos pradžią jie kartu parengia 100500 XNUMX skaidrių ta tema (pvz., problemos su paketais C++ arba generinių žodžių trūkumas programoje Go), o tada jie aktyviai diskutuoja tarpusavyje ir su auditorija, o auditorija bando suprasti du požiūrius vienu metu. Jei holivaras prasideda iš konteksto, moderatorius įsikiša ir sutaiko šalis. Šis formatas sukelia priklausomybę: praėjus kelioms valandoms po starto, buvo įveikta tik pusė skaidrių. Pabaigą teko gerokai paspartinti.

  • Partnerių stendai

Konferencijos partneriai buvo atstovaujami salėse - stenduose kalbėjo apie vykdomus projektus, siūlė stažuotes ir įsidarbinimą, vyko viktorinos ir nedideli konkursai, taip pat išlošė gražius prizus. Tuo pačiu metu kai kurios įmonės net siūlė pereiti pradinius pokalbių etapus, kurie gali būti naudingi atėjusiems ne tik pasiklausyti pranešimų.

Techninė ataskaitų informacija

Abi dienas klausėmės pranešimų. Kartais būdavo sunku išsirinkti vieną reportažą iš paralelinių – susitardavome išsiskirstyti ir pasidalinti įgytomis žiniomis per pertraukas. Ir net ir taip atrodo, kad daug kas palikta. Čia norėtume pakalbėti apie kai kurių mums įdomiausių ataskaitų turinį

Išimtys C++ per kompiliatoriaus optimizavimo prizmę, Roman Rusyaev

C++ Rusija: kaip tai atsitiko
Slysti iš pristatymai

Kaip rodo pavadinimas, Romanas pažvelgė į darbą su išimtimis, kaip pavyzdį naudodamas LLVM. Tuo pačiu metu tiems, kurie savo darbe nenaudoja Clang, ataskaita vis tiek gali suteikti supratimo apie tai, kaip kodą būtų galima optimizuoti. Taip yra todėl, kad kompiliatorių ir atitinkamų standartinių bibliotekų kūrėjai bendrauja tarpusavyje ir gali sutapti daug sėkmingų sprendimų.

Taigi, norint išspręsti išimtį, reikia atlikti daugybę dalykų: iškviesti tvarkymo kodą (jei yra) arba atlaisvinti esamo lygio išteklius ir pakelti krūvą aukščiau. Visa tai lemia tai, kad kompiliatorius prideda papildomų instrukcijų skambučiams, kurie gali sukelti išimtis. Todėl, jei išimtis iš tikrųjų nebus iškelta, programa vis tiek atliks nereikalingus veiksmus. Siekiant kažkaip sumažinti pridėtines išlaidas, LLVM turi keletą euristikos, skirtų nustatyti situacijas, kai nereikia pridėti išimčių tvarkymo kodo arba galima sumažinti „papildomų“ instrukcijų skaičių.

Pranešėjas išnagrinėja apie dešimt jų ir parodo ir situacijas, kai jos padeda pagreitinti programos vykdymą, ir tas, kur šie metodai nepritaikomi.

Taigi, Romanas Rusjajevas veda studentus prie išvados, kad kodas, kuriame yra išimčių tvarkymas, ne visada gali būti vykdomas be jokių papildomų išlaidų, ir pateikia šiuos patarimus:

  • kuriant bibliotekas verta iš esmės atsisakyti išimčių;
  • jei dar reikia išimčių, tada, kai tik įmanoma, verta visur pridėti modifikatorių noexcept (ir const), kad kompiliatorius galėtų kuo daugiau optimizuoti.

Apskritai pranešėjas patvirtino nuomonę, kad išimtis geriausia išnaudoti iki minimumo arba jų iš viso atsisakyti.

Ataskaitų skaidres rasite paspaudę šią nuorodą: ["C++ išimtys per LLVM kompiliatoriaus optimizavimo objektyvą"]

Generatoriai, korutinos ir kiti smegenis išvyniojantys saldumynai, Adi Shavit

C++ Rusija: kaip tai atsitiko
Slysti iš pristatymai

Vienas iš daugelio šios konferencijos pranešimų, skirtų C++20 naujovėms, įsiminė ne tik spalvingu pristatymu, bet ir aiškiu esamų problemų, susijusių su kolekcijos apdorojimo logika (for loop, callbacks), identifikavimu.

Adi Shavit pabrėžia šiuos dalykus: šiuo metu galimi metodai pereina per visą kolekciją ir nesuteikia prieigos prie tam tikros vidinės tarpinės būsenos (arba jie daro atgalinio skambučio atveju, tačiau turi daug nemalonių šalutinių poveikių, pvz., Atšaukimo pragaras) . Atrodytų, kad yra iteratorių, bet ir su jais viskas ne taip sklandžiai: nėra bendrų įėjimo ir išėjimo taškų (pradžia → pabaiga versus rbegin → rend ir panašiai), neaišku, kiek laiko kartosimės? Pradedant nuo C++20, šios problemos išspręstos!

Pirmasis variantas: diapazonai. Apvyniodami iteratorius, gauname bendrą sąsają iteracijos pradžiai ir pabaigai, taip pat gauname galimybę kurti. Visa tai leidžia lengvai sukurti visaverčius duomenų apdorojimo vamzdynus. Tačiau ne viskas taip sklandu: dalis skaičiavimo logikos yra konkretaus iteratoriaus diegimo viduje, o tai gali apsunkinti kodo supratimą ir derinimą.

C++ Rusija: kaip tai atsitiko
Slysti iš pristatymai

Na, šiuo atveju C++20 pridėjo korutinos (funkcijos, kurių elgesys yra panašus į Python generatorių): vykdymas gali būti atidėtas grąžinant tam tikrą dabartinę vertę, išsaugant tarpinę būseną. Taigi pasiekiame ne tik darbą su tokiais duomenimis, kokie jie atrodo, bet ir visą logiką įterpti į konkrečios korutinos viduje.

Tačiau yra skraidymas: šiuo metu juos tik iš dalies palaiko esami kompiliatoriai, taip pat nėra taip tvarkingai įgyvendinami, kaip norėtume: pavyzdžiui, nuorodų ir laikinų objektų korutinose naudoti dar neverta. Be to, yra tam tikrų apribojimų, kas gali būti korutines, o constexpr funkcijos, konstruktoriai / naikintojai ir pagrindinis į šį sąrašą neįtraukti.

Taigi, korutinos nemažą dalį problemų išsprendžia duomenų apdorojimo logikos paprastumu, tačiau dabartinis jų įgyvendinimas reikalauja tobulinimo.

Medžiagos:

C++ gudrybės iš Yandex.Taxi, Anton Polukhin

Profesinėje veikloje kartais tenka diegti grynai pagalbinius dalykus: vyniojimą tarp vidinės sąsajos ir kokios nors bibliotekos API, registravimą ar analizavimą. Tokiu atveju paprastai nereikia jokio papildomo optimizavimo. Bet ką daryti, jei šie komponentai naudojami kai kuriose populiariausiose „RuNet“ paslaugose? Esant tokiai situacijai, turėsite apdoroti vien terabaitus per valandą žurnalų! Tuomet svarbi kiekviena milisekundė ir todėl tenka griebtis įvairių gudrybių – apie juos kalbėjo Antonas Polukhinas.

Bene įdomiausias pavyzdys buvo rodyklės į įgyvendinimą (pimpl) modelio įgyvendinimas. 

#include <third_party/json.hpp> //PROBLEMS! 
struct Value { 
    Value() = default; 
    Value(Value&& other) = default; 
    Value& operator=(Value&& other) = default; 
    ~Value() = default; 

    std::size_t Size() const { return data_.size(); } 

private: 
    third_party::Json data_; 
};

Šiame pavyzdyje pirmiausia noriu atsikratyti išorinių bibliotekų antraščių failų – taip sukompiliuosite greičiau ir galėsite apsisaugoti nuo galimų pavadinimų konfliktų ir kitų panašių klaidų. 

Gerai, #include perkėlėme į .cpp failą: mums reikia išankstinės suvyniotos API deklaracijos, taip pat std::unique_ptr. Dabar turime dinaminius paskirstymus ir kitus nemalonius dalykus, pvz., duomenis, išsklaidytus daugybėje duomenų, ir sumažintas garantijas. std::aligned_storage gali padėti visa tai. 

struct Value { 
// ... 
private: 
    using JsonNative = third_party::Json; 
    const JsonNative* Ptr() const noexcept; 
    JsonNative* Ptr() noexcept; 

    constexpr std::size_t kImplSize = 32; 
    constexpr std::size_t kImplAlign = 8; 
    std::aligned_storage_t<kImplSize, kImplAlign> data_; 
};

Vienintelė problema: reikia nurodyti kiekvieno įvynioklio dydį ir lygiavimą – sukurkime pimpl šabloną su parametrais , naudokite kai kurias savavališkas reikšmes ir pridėkite naikintuvo patikrinimą, ar viskas gerai: 

~FastPimpl() noexcept { 
    validate<sizeof(T), alignof(T)>(); 
    Ptr()->~T(); 
}

template <std::size_t ActualSize, std::size_t ActualAlignment>
static void validate() noexcept { 
    static_assert(
        Size == ActualSize, 
        "Size and sizeof(T) mismatch"
    ); 
    static_assert(
        Alignment == ActualAlignment, 
        "Alignment and alignof(T) mismatch"
    ); 
}

Kadangi T jau yra apibrėžtas apdorojant destruktorių, šis kodas bus tinkamai išanalizuotas ir kompiliavimo etape išves reikiamą dydį ir lygiavimo reikšmes, kurias reikia įvesti kaip klaidas. Taigi už vieną papildomą kompiliavimo paleidimą atsikratome dinamiško suvyniotų klasių paskirstymo, paslėpiame API .cpp faile su diegimu, taip pat gauname dizainą, kuris labiau tinka procesoriaus talpykloje.

Registravimas ir analizavimas atrodė mažiau įspūdingi, todėl šioje apžvalgoje jie nebus paminėti.

Ataskaitų skaidres rasite paspaudę šią nuorodą: ["C++ gudrybės iš taksi"]

Šiuolaikiniai būdai, kaip išlaikyti jūsų kodą SAUSUS, Björn Fahller

Šioje kalboje Björnas Fahleris parodo kelis skirtingus būdus, kaip kovoti su stilistiniais pasikartojančių būklės patikrinimų trūkumais:

assert(a == IDLE || a == CONNECTED || a == DISCONNECTED);

Skamba pažįstamai? Naudodami keletą galingų C++ metodų, įdiegtų naujausiuose standartuose, galite elegantiškai įgyvendinti tą pačią funkciją be jokios našumo nuobaudos. Palyginti:   

assert(a == any_of(IDLE, CONNECTED, DISCONNECTED));

Norėdami atlikti nefiksuotą patikrinimų skaičių, iš karto turite naudoti įvairius šablonus ir lenkimo išraiškas. Tarkime, kad norime patikrinti kelių kintamųjų lygybę enum elementui state_type. Pirmas dalykas, kuris ateina į galvą, yra parašyti pagalbinę funkciją is_any_of:


enum state_type { IDLE, CONNECTED, DISCONNECTED };

template <typename ... Ts>
bool is_any_of(state_type s, const Ts& ... ts) { 
    return ((s == ts) || ...); 
}

Šis tarpinis rezultatas nuvilia. Kol kas kodas netampa aiškesnis:

assert(is_any_of(state, IDLE, DISCONNECTING, DISCONNECTED)); 

Ne tipo šablono parametrai padės šiek tiek pagerinti situaciją. Su jų pagalba mes perkelsime suskaičiuojamus sąrašo elementus į šablono parametrų sąrašą: 

template <state_type ... states>
bool is_any_of(state_type t) { 
    return ((t == states) | ...); 
}
	
assert(is_any_of<IDLE, DISCONNECTING, DISCONNECTED>(state)); 

Naudojant automatinį ne tipo šablono parametrą (C++17), metodas tiesiog apibendrina palyginimus ne tik su state_type elementais, bet ir su primityviais tipais, kurie gali būti naudojami kaip ne tipo šablono parametrai:


template <auto ... alternatives, typename T>
bool is_any_of(const T& t) {
    return ((t == alternatives) | ...);
}

Dėl šių nuoseklių patobulinimų pasiekiama norima sklandi čekių sintaksė:


template <class ... Ts>
struct any_of : private std::tuple<Ts ...> { 
// поленимся и унаследуем конструкторы от tuple 
        using std::tuple<Ts ...>::tuple;
        template <typename T>
        bool operator ==(const T& t) const {
                return std::apply(
                        [&t](const auto& ... ts) {
                                return ((ts == t) || ...);
                        },
                        static_cast<const std::tuple<Ts ...>&>(*this));
        }
};

template <class ... Ts>
any_of(Ts ...) -> any_of<Ts ... >;
 
assert(any_of(IDLE, DISCONNECTING, DISCONNECTED) == state);

Šiame pavyzdyje išskaičiavimo vadovas padeda pasiūlyti norimus struktūros šablono parametrus kompiliatoriui, kuris žino konstruktoriaus argumentų tipus. 

Toliau – įdomiau. Bjornas moko, kaip apibendrinti gautą kodą palyginimo operatoriams po ==, o tada savavališkoms operacijoms. Be to, tokios funkcijos kaip no_unique_address atributas (C++20) ir šablono parametrai lambda funkcijose (C++20) paaiškinami naudojant naudojimo pavyzdžius. (Taip, dabar lambda sintaksė dar lengviau įsimenama – tai keturios iš eilės visų rūšių skliaustų poros.) Galutinis sprendimas, naudojant funkcijas kaip konstruktoriaus detales, tikrai sušildo mano sielą, jau nekalbant apie posakių eilutę geriausiose lambda tradicijose skaičiavimas.

Pabaigoje nepamirškite nušlifuoti:

  • Atminkite, kad lambdas yra constexpr nemokamai; 
  • Pridėkime tobulą persiuntimą ir pažiūrėkime į jo bjaurią sintaksę, susijusią su parametrų paketu lambda uždoryje;
  • Suteikime kompiliatoriui daugiau optimizavimo galimybių su sąlyginiu išskyrus; 
  • Pasirūpinkime suprantamesne klaidų išvestimi šablonuose dėl aiškių lambdas grąžinimo verčių. Tai privers kompiliatorių atlikti daugiau patikrinimų prieš iš tikrųjų iškviečiant šablono funkciją – tipo tikrinimo etape. 

Daugiau informacijos rasite paskaitų medžiagoje: 

Mūsų įspūdžiai

Pirmasis mūsų dalyvavimas C++ Rusijoje įsiminė savo intensyvumu. C++ Rusija man susidarė įspūdis kaip nuoširdus renginys, kur riba tarp treniruočių ir gyvo bendravimo beveik nepastebima. Viskas – nuo ​​pranešėjų nuotaikos iki renginio partnerių varžytuvių – palanku karštoms diskusijoms. Konferencijos turinys, kurį sudaro pranešimai, apima gana platų temų spektrą, įskaitant C++ inovacijas, didelių projektų atvejų analizę ir ideologinius architektūrinius svarstymus. Tačiau būtų nesąžininga ignoruoti socialinį renginio komponentą, kuris padeda įveikti kalbos barjerus, susijusius ne tik su C++.

Dėkojame konferencijos organizatoriams už galimybę dalyvauti tokiame renginyje!
Galbūt matėte organizatorių įrašą apie C++ Rusijos praeitį, dabartį ir ateitį tinklaraštyje JUG Ru.

Dėkojame, kad skaitėte, ir tikimės, kad mūsų įvykių perpasakojimas buvo naudingas!

Šaltinis: www.habr.com

Добавить комментарий