C ++ Ruslân: hoe't it barde

As jo ​​oan it begjin fan it toanielstik sizze dat der C++-koade oan 'e muorre hinget, dan is it oan 'e ein bûn om jo yn 'e foet te sjitten.

Bjarne Stroustrup

Fan 31 oktober oant 1 novimber waard yn Sint-Petersburch de C++ Russia Piter-konferinsje hâlden - ien fan de grutskalige programmearrings yn Ruslân, organisearre troch JUG Ru Group. Gastsprekkers omfetsje leden fan it C++ Standards Committee, CppCon-sprekkers, O'Reilly-boekauteurs, en ûnderhâlders fan projekten lykas LLVM, libc++, en Boost. De konferinsje is rjochte op betûfte C++-ûntwikkelders dy't har saakkundigens ferdjipje wolle en ûnderfiningen yn live kommunikaasje útwikselje wolle. Studinten, ôfstudearden en universitêre dosinten krije tige moaie koartingen.

De Moskouske edysje fan 'e konferinsje sil beskikber wêze om te besykjen sa betiid as april takom jier, mar yn 'e tuskentiid ús studinten sille fertelle wat nijsgjirrige dingen se leard op it lêste evenemint. 

C ++ Ruslân: hoe't it barde

Фото из konferinsje album

Oer ús

Twa studinten fan 'e National Research University Higher School of Economics - Sint-Petersburch wurken oan dizze post:

  • Liza Vasilenko is in 4e jier undergraduate studint dy't programmearring talen studearret as ûnderdiel fan it programma Applied Mathematics and Computer Science. Nei't ik yn myn earste jier op de universiteit yn 'e kunde kommen wie mei de C++-taal, haw ik dêrnei ûnderfining opdien troch staazjes yn 'e yndustry. Myn passy foar programmeartalen yn it algemien en funksjonele programmearring yn it bysûnder liet syn stimpel efter op de seleksje fan rapporten op de konferinsje.
  • Danya Smirnov is in 1e jier studint fan it masterprogramma "Programmering en gegevensanalyse". Wylst noch op skoalle skreau ik Olympiadeproblemen yn C++, en doe barde it op ien of oare manier dat de taal hieltyd opkaam yn edukative aktiviteiten en úteinlik de wichtichste wurktaal waard. Ik besleat om mei te dwaan oan 'e konferinsje om myn kennis te ferbetterjen en ek te learen oer nije kânsen.

Yn 'e nijsbrief dielt de fakulteitslieding faak ynformaasje oer edukative eveneminten yn ferbân mei ús spesjaliteit. Yn septimber seagen wy ynformaasje oer C++ Ruslân en besletten om te registrearjen as harkers. Dit is ús earste ûnderfining fan meidwaan oan sokke konferinsjes.

Konferinsje struktuer

  • Ferslaggen

Yn 'e rin fan twa dagen lêze saakkundigen 30 rapporten, dy't in protte waarme ûnderwerpen behannelje: geniaal gebrûk fan taalfunksjes om tapaste problemen op te lossen, kommende taalfernijings yn ferbân mei de nije standert, kompromissen yn C++-ûntwerp en foarsoarchsmaatregels by it wurkjen mei har gefolgen, foarbylden fan nijsgjirrige projektarsjitektuer, lykas guon ûnder-de-kap details fan 'e taalynfrastruktuer. Trije foarstellings fûnen tagelyk plak, meast twa yn it Russysk en ien yn it Ingelsk.

  • Diskusje sônes

Nei de taspraak waarden alle net stelde fragen en ûnfoltôge diskusjes oerbrocht nei spesjaal oanwiisde gebieten foar kommunikaasje mei de sprekkers, útrist mei markearplaten. In goede manier om de pauze tusken de taspraken te ferbrekken mei in noflik petear.

  • Lightning Talks en ynformele diskusjes

As jo ​​​​in koart ferslach wolle jaan, kinne jo jo op it whiteboard oanmelde foar de jûn Lightning Talk en krije fiif minuten tiid om oer alles oer it konferinsjeûnderwerp te praten. Bygelyks, in flugge yntroduksje ta sanitizers foar C ++ (foar guon wie it nij) of in ferhaal oer in brek yn sinuswave-generaasje dy't allinich kin wurde heard, mar net sjoen.

In oare opmaak is de paneldiskusje "Mei in Heart to Heart Committee." Op it poadium binne guon leden fan 'e standerdisearringskommisje, op' e projektor is in fjoerplak (offisjeel - om in oprjochte sfear te meitsjen, mar de reden "omdat ALLES ON FIRE" liket grappiger), fragen oer de standert en de algemiene fisy fan C++ , sûnder heftige technyske diskusjes en holiwars. It die bliken dat yn de kommisje ek libbene minsken sitte dy't der miskien net hielendal wis fan binne of wat net witte.

Foar fans fan holivars bleau it tredde evenemint op 'e saak - de BOF-sesje "Go vs. C ++". Wy nimme in Go-leafhawwer, in C++-leafhawwer, foar it begjin fan 'e sesje meitsje se tegearre 100500 dia's tariede oer in ûnderwerp (lykas problemen mei pakketten yn C++ of it gebrek oan generika yn Go), en dan hawwe se in libbene diskusje ûnderinoar en mei it publyk, en it publyk besiket twa stânpunten tagelyk te begripen. As in holivar bûten kontekst begjint, grypt de moderator yn en fermoedsoenet de partijen. Dit formaat is ferslaavjend: ferskate oeren nei it begjin wie mar de helte fan 'e dia's foltôge. De ein moast flink fersneld wurde.

  • Partner stiet

De partners fan 'e konferinsje wiene yn 'e sealen fertsjintwurdige - op 'e tribunes prate se oer aktuele projekten, biede staazjeplakken en wurkgelegenheid oan, holden kwissen en lytse wedstriden, en lutsen ek moaie prizen út. Tagelyk, guon bedriuwen sels oanbean te gean troch de earste fazen fan ynterviews, dat koe wêze nuttich foar dyjingen dy't kamen net allinne te harkjen nei rapporten.

Technyske details fan 'e rapporten

Мы слушали доклады оба дня. Порой было трудно выбрать один доклад из параллельно идущих – мы договорились разделяться и обмениваться полученными знаниями в перерывах. И даже так, кажется, что многое осталось упущено. Здесь мы хотели бы рассказать о содержании некоторых докладов, которые показались нам самыми интересными

Utsûnderings yn C ++ troch it prisma fan gearstaller optimizations, Roman Rusyaev

C ++ Ruslân: hoe't it barde
Slide fan presintaasjes

Как понятно из названия, Роман рассмотрел работу с исключениями на примере LLVM. При этом для не использующих в своей работе Clang доклад всё равно может дать некоторое представление о том, как код потенциально может быть оптимизирован. Это так, потому что разработчики компиляторов и соответствующих стандартных библиотек общаются между собой и многие удачные решения могут совпадать.

Dus, om in útsûndering te behanneljen, moatte jo in protte dingen dwaan: skilje de ôfhannelingskoade (as ien) of frije boarnen op it hjoeddeistige nivo en spin de stapel heger. Dit alles liedt ta it feit dat de gearstaller ekstra ynstruksjes tafoeget foar petearen dy't mooglik útsûnderings smyt. Dêrom, as de útsûndering net echt opheft is, sil it programma noch ûnnedige aksjes útfiere. Om ien of oare manier te ferminderjen overhead, hat LLVM ferskate heuristics foar it bepalen fan situaasjes dêr't útsûndering ôfhanneling koade net hoege wurde tafoege of it oantal "ekstra" ynstruksjes kin wurde fermindere.

De sprekker ûndersiket sa'n tsientallen fan har en lit beide situaasjes sjen wêr't se de útfiering fan programma's helpe te fersnellen, en dyjingen wêr't dizze metoaden net fan tapassing binne.

Sa, Roman Rusyaev liedt studinten ta de konklúzje dat koade mei útsûndering ôfhanneling kin net altyd wurde útfierd mei nul overhead, en jout de folgjende advys:

  • by it ûntwikkeljen fan bibleteken is it yn prinsipe de muoite wurdich om útsûnderingen te ferlitten;
  • as der noch útsûnderings nedich binne, dan is it, as it mooglik is, it wurdich oeral noexcept (en const) modifiers ta te foegjen, sadat de kompilator safolle mooglik optimalisearje kin.

Yn 't algemien befêstige de sprekker de opfetting dat útsûnderingen it bêste oant in minimum brûkt wurde of hielendal ferlitten wurde.

De rapportdia's binne beskikber op de folgjende link: ["C ++ útsûnderingen troch de lens fan LLVM-kompilatoroptimisaasjes"]

Generators, coroutines and other brain-unrolling sweetness, Adi Shavit

C ++ Ruslân: hoe't it barde
Slide fan presintaasjes

Ien fan de protte rapporten op dizze konferinsje wijd oan ynnovaasjes yn C ++ 20 wie memorabel net allinnich foar syn kleurrike presintaasje, mar ek foar syn dúdlike identifikaasje fan besteande problemen mei de kolleksje ferwurkjen logika (foar loop, callbacks).

Adi Shavit markearret it folgjende: de op it stuit beskikbere metoaden geane troch de hiele kolleksje en jouwe gjin tagong ta guon ynterne tuskenstân (of se dogge yn it gefal fan callbacks, mar mei in grut oantal ûnnoflike side-effekten, lykas Callback Hell) . It soe lykje dat der iterators, mar ek mei harren is alles net sa glêd: der binne gjin mienskiplike yngong en útgong punten (begjin → ein tsjin rbegin → rend ensafuorthinne), it is net dúdlik hoe lang wy sille iterearje? Begjinnend mei C ++ 20 binne dizze problemen oplost!

Earste opsje: berik. Troch iterators yn te pakken krije wy in mienskiplike ynterface foar it begjin en ein fan in iteraasje, en wy krije ek de mooglikheid om te komponearjen. Dit alles makket it maklik om folweardige pipelines foar gegevensferwurking te bouwen. Mar net alles is sa glêd: in diel fan 'e berekkeningslogika leit binnen de ymplemintaasje fan in spesifike iterator, dy't de koade komplisearje kin om te begripen en te debuggen.

C ++ Ruslân: hoe't it barde
Slide fan presintaasjes

No, foar dit gefal, C ++ 20 tafoege coroutines (funksjes waans gedrach is fergelykber mei generators yn Python): útfiering kin wurde útsteld troch in weromkear wat aktuele wearde wylst behâld fan in tuskenlizzende steat. Sa berikke wy net allinich wurkjen mei gegevens sa't it ferskynt, mar ek it ynkapseljen fan alle logika binnen in spesifike koroutine.

Mar der sit in flinter yn 'e salve: se wurde op it stuit mar foar in part stipe troch besteande gearstallers, en ek net sa kreas útfierd as wy wolle: it is bygelyks noch net de muoite wurdich om ferwizings en tydlike objekten yn koroutines te brûken. Plus, d'r binne wat beheiningen op wat kin wêze coroutines, en constexpr funksjes, constructors / destructors, en main binne net opnommen yn dizze list.

Sa losse koroutines in wichtich part fan 'e problemen op mei de ienfâld fan logika foar gegevensferwurking, mar har hjoeddeistige ymplemintaasjes fereaskje ferbettering.

Materialen:

C ++ tricks út Yandex.Taxi, Anton Polukhin

Yn myn profesjonele aktiviteiten, soms moat ik útfiere suver auxiliaire dingen: in wrapper tusken de ynterne ynterface en de API fan guon bibleteek, logging of parsing. Yn dit gefal is d'r normaal gjin ekstra optimalisaasje nedich. Mar wat as dizze komponinten wurde brûkt yn guon fan 'e populêrste tsjinsten op it RuNet? Yn sa'n situaasje moatte jo allinich terabytes per oere oan logs ferwurkje! Dan telt elke millisekonde en dêrom moatte jo taflecht ta ferskate trúkjes - Anton Polukhin praat oer harren.

Miskien wie it meast nijsgjirrige foarbyld de ymplemintaasje fan it pointer-to-implementation (pimpl) patroan. 

#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_; 
};

В данном примере сначала хочется избавиться от заголовочных файлов внешних библиотек — так и компилироваться будет быстрее, и можно обезопасить себя от возможных конфликтов имён и других подобных ошибок. 

Okee, wy hawwe #include ferpleatst nei it .cpp-bestân: wy hawwe in foarút-ferklearring nedich fan 'e ynpakt API, lykas std :: unique_ptr. No hawwe wy dynamyske allocaasjes en oare onaangename dingen lykas gegevens ferspraat oer in boskje gegevens en fermindere garânsjes. std :: aligned_storage kin helpe mei dit alles. 

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_; 
};

It ienige probleem: jo moatte de grutte en ôfstimming foar elke wrapper opjaan - litte wy ús pimpl-sjabloan meitsje mei parameters , brûk wat willekeurige wearden en foegje in kontrôle ta oan 'e destruktor dat wy alles goed hawwe: 

~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"
    ); 
}

Так как при обработке деструктора T уже определён, данный код будет разбираться корректно и на стадии компиляции в виде ошибок выведет нужные значения размера и выравнивания, которые нужно вписать. Таким образом, ценой одного дополнительного запуска компиляции мы избавляемся от динамической аллокации оборачиваемых классов, прячем API в .cpp-файл с реализацией, а также получаем более пригодную для кеширования процессором конструкцию.

Logging en parsing like minder yndrukwekkend en wurde dêrom net neamd yn dizze resinsje.

De rapportdia's binne beskikber op de folgjende link: ["C++ trúkjes fan Taxi"]

Moderne techniken foar it hâlden fan jo koade DRY, Björn Fahller

Yn dit petear lit Björn Fahller ferskate ferskillende manieren sjen om de stilistyske flater fan werhelle kondysjekontrôles te bestriden:

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

Klinkt bekend? Troch it brûken fan ferskate krêftige C ++ techniken yntrodusearre yn resinte noarmen, kinne jo elegant útfiere deselde funksjonaliteit sûnder hokker prestaasje straf. Ferlykje:   

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

Om in ûnbepaald oantal kontrôles te behanneljen, moatte jo daliks fariabele sjabloanen en fold-útdrukkingen brûke. Lit ús oannimme dat wy wolle kontrolearje de gelikensens fan ferskate fariabelen oan de enum syn state_type elemint. It earste ding dat yn 't sin komt is om in helperfunksje te skriuwen 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) || ...); 
}

Dit tuskenresultaat is teloarstellend. Oant no wurdt de koade net mear lêsber:

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

Non-type sjabloanparameters sille helpe om de situaasje in bytsje te ferbetterjen. Mei har help sille wy de optelbere eleminten fan 'e enum oerdrage nei de list mei sjabloanparameters: 

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

Troch auto te brûken yn in net-type sjabloanparameter (C++17), generalisearret de oanpak gewoan nei fergelikingen net allinich mei state_type-eleminten, mar ek mei primitive typen dy't brûkt wurde kinne as net-type sjabloanparameters:


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

Troch dizze opienfolgjende ferbetterings wurdt de winske floeiende syntaksis foar kontrôles berikt:


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);

Yn dit foarbyld tsjinnet de ôfliedingsgids om de winske struktuersjabloanparameters foar te stellen oan 'e gearstaller, dy't de soarten fan' e konstruktorarguminten wit. 

Fierder - mear nijsgjirrich. Bjorn leart hoe te generalisearjen de resultearjende koade foar ferliking operators foarby ==, en dan foar willekeurige operaasjes. Underweis wurde sokke funksjes as no_unique_address attribút (C ++20) en sjabloanparameters yn lambdafunksjes (C ++20) útlein mei gebrûk fan foarbylden. (Ja, no is de lambda-syntaksis noch makliker te ûnthâlden - dit binne fjouwer opienfolgjende pearen fan alle soarten haakjes.) De definitive oplossing mei funksjes as konstruktordetails waarmet myn siel echt, om net te sprekken fan de útdrukking tuple yn 'e bêste tradysjes fan lambda calculus.

Oan 'e ein, ferjit it net te poetsen:

  • Unthâld dat lambdas binne constexpr fergees; 
  • Litte wy perfekte trochstjoere tafoegje en nei syn ûnsjogge syntaksis sjen yn relaasje ta it parameterpakket yn 'e lambda-sluting;
  • Litte wy de kompilator mear kânsen jaan foar optimisaasjes mei betingst noexcept; 
  • Litte wy soargje foar mear begryplike flaterútfier yn sjabloanen troch eksplisite weromwearden fan lambda's. Dit sil de kompilator twinge om mear kontrôles te dwaan foardat de sjabloanfunksje eins wurdt oanroppen - by it typekontrôlestadium. 

Foar details, ferwize asjebleaft it lêsmateriaal: 

Us yndrukken

Us earste dielname oan C ++ Ruslân wie memorabel foar syn yntensiteit. Ik krige de yndruk fan C ++ Ruslân as in oprjocht barren, dêr't de line tusken training en live kommunikaasje is hast net te merken. Alles, fan 'e stimming fan' e sprekkers oant de kompetysjes fan 'e evenemintpartners, is befoarderlik foar fûle diskusjes. De ynhâld fan 'e konferinsje, besteande út rapporten, beslacht in frij breed skala oan ûnderwerpen ynklusyf C ++ ynnovaasjes, case studies fan grutte projekten en ideologyske arsjitektoanyske oerwagings. Mar it soe ûnrjochtfeardich wêze om de sosjale komponint fan it evenemint te negearjen, wat helpt om taalbarriêres te oerwinnen yn relaasje net allinich mei C ++.

Wy tankje de organisatoaren fan de konferinsje foar de mooglikheid om mei te dwaan oan sa'n evenemint!
Jo hawwe miskien de post fan 'e organisatoaren sjoen oer it ferline, hjoed en takomst fan C ++ Ruslân op it JUG Ru-blog.

Tank foar it lêzen, en wy hoopje dat ús opnij fertellen fan eveneminten nuttich wie!

Boarne: www.habr.com

Add a comment