C++ Krievija: kā tas notika

Ja lugas sākumā tu saki, ka pie sienas karājās C++ kods, tad beigās tas noteikti ieŔaus tev kājā.

Bjarne Stroustrup

No 31. oktobra lÄ«dz 1. novembrim Sanktpēterburgā norisinājās C++ Russia Piter konference - viena no vērienÄ«gajām programmÄ“Å”anas konferencēm Krievijā, ko organizēja JUG Ru Group. Vieslektoru vidÅ« ir C++ standartu komitejas locekļi, CppCon runātāji, O'Reilly grāmatu autori un tādu projektu uzturētāji kā LLVM, libc++ un Boost. Konference ir paredzēta pieredzējuÅ”iem C++ izstrādātājiem, kuri vēlas padziļināt savas zināŔanas un apmainÄ«ties ar pieredzi dzÄ«vajā komunikācijā. Studentiem, maÄ£istrantiem un augstskolu pasniedzējiem tiek nodroÅ”inātas ļoti jaukas atlaides.

Konferences Maskavas izdevumu varēs apmeklēt jau nākamā gada aprÄ«lÄ«, bet tikmēr mÅ«su studenti pastāstÄ«s, ko interesantu viņi uzzināja pēdējā pasākumā. 

C++ Krievija: kā tas notika

Foto no konferences albums

Par mums

Divi studenti no Nacionālās pētniecÄ«bas universitātes Augstākās ekonomikas skolas Sanktpēterburgā strādāja pie Ŕī amata:

  • Liza Vasiļenko ir 4. kursa bakalaura studente, kas LietiŔķās matemātikas un datorzinātņu programmas ietvaros studē programmÄ“Å”anas valodas. IepazÄ«stoties ar C++ valodu pirmajā augstskolas kursā, pēc tam guvu pieredzi darbā ar to, stažējoties nozarē. Mana aizrauÅ”anās ar programmÄ“Å”anas valodām kopumā un jo Ä«paÅ”i funkcionālo programmÄ“Å”anu atstāja savas pēdas konferences referātu atlasē.
  • Danija Smirnova ir maÄ£istra programmas ā€œProgrammÄ“Å”ana un datu analÄ«zeā€ 1. kursa studente. Vēl mācoties skolā, es rakstÄ«ju olimpiādes uzdevumus C++ valodā, un tad kaut kā sanāca tā, ka valoda nemitÄ«gi parādÄ«jās izglÄ«tÄ«bas pasākumos un galu galā kļuva par galveno darba valodu. Nolēmu piedalÄ«ties konferencē, lai pilnveidotu savas zināŔanas un arÄ« uzzinātu par jaunām iespējām.

Biļetenā fakultātes vadÄ«ba bieži dalās ar informāciju par izglÄ«tÄ«bas pasākumiem, kas saistÄ«ti ar mÅ«su specialitāti. SeptembrÄ« mēs redzējām informāciju par C++ Krieviju un nolēmām reÄ£istrēties kā klausÄ«tāji. Å Ä« ir mÅ«su pirmā pieredze, piedaloties Ŕādās konferencēs.

Konferences struktūra

  • Pārskati

Divu dienu laikā eksperti nolasÄ«ja 30 ziņojumus, aptverot daudzas aktuālas tēmas: Ä£eniāls valodas funkciju lietojums lietiŔķo problēmu risināŔanai, gaidāmie valodas atjauninājumi saistÄ«bā ar jauno standartu, kompromisi C++ dizainā un piesardzÄ«bas pasākumi, strādājot ar to sekām, piemēri. interesantu projektu arhitektÅ«ru, kā arÄ« dažas valodas infrastruktÅ«ras detaļas. VienlaicÄ«gi notika trÄ«s izrādes, visbiežāk divas krievu un viena angļu valodā.

  • Diskusiju zonas

Pēc uzstāŔanās visi neuzdotie jautājumi un nepabeigtās diskusijas tika pārceltas uz speciāli saziņai ar runātājiem paredzētām zonām, kas aprÄ«kotas ar marÄ·ieru dēļiem. Labs veids, kā atpÅ«sties starp runām ar patÄ«kamu sarunu.

  • Zibens sarunas un neformālas diskusijas

Ja vēlaties sniegt Ä«su ziņojumu, varat pierakstÄ«ties uz tāfeles vakara zibens sarunām un iegÅ«t piecas minÅ«tes laika, lai runātu par jebko par konferences tēmu. Piemēram, Ä«ss ievads par dezinfekcijas lÄ«dzekļiem priekÅ” C++ (dažiem tas bija jaunums) vai stāsts par sinusoidālā viļņa Ä£enerÄ“Å”anas kļūdu, kuru var tikai dzirdēt, bet neredzēt.

Cits formāts ir paneļdiskusija ā€œAr sirdi uz sirdi komitejaā€. Uz skatuves ir daži standartizācijas komitejas locekļi, uz projektora ir kamÄ«ns (oficiāli - lai radÄ«tu sirsnÄ«gu atmosfēru, bet jocÄ«gāks Ŕķiet iemesls "jo VISS dega"), jautājumi par standartu un C++ vispārējo redzējumu. , bez karstām tehniskām diskusijām un holivariem. IzrādÄ«jās, ka komitejā ir arÄ« dzÄ«vi cilvēki, kuri var nebÅ«t par kaut ko lÄ«dz galam pārliecināti vai kaut ko nezināt.

Holivaru cienÄ«tājiem pie lietas palika treÅ”ais notikums - BOF sesija ā€œGo vs. C++ā€. Mēs uzņemam Go mīļotāju, C++ cienÄ«tāju, pirms sesijas sākuma viņi kopā sagatavo 100500 XNUMX slaidus par tēmu (piemēram, problēmas ar pakotnēm C++ vai vispārÄ«go lÄ«dzekļu trÅ«kums programmā Go), un pēc tam viņi savā starpā aktÄ«vi apspriežas. ar auditoriju, un auditorija mēģina saprast divus viedokļus vienlaikus. Ja holivar sākas ārpus konteksta, moderators iejaucas un samierina puses. Å is formāts rada atkarÄ«bu: vairākas stundas pēc starta tika pabeigta tikai puse no slaidiem. Beigas bija krietni jāpaātrina.

  • Partneru stendi

Konferences partneri bija pārstāvēti zālēs - stendos stāstÄ«ja par aktuālajiem projektiem, piedāvāja prakses un nodarbinātÄ«bas vietas, rÄ«koja viktorÄ«nas un nelielus konkursus, kā arÄ« izlozēja jaukas balvas. Tajā paŔā laikā daži uzņēmumi pat piedāvāja iziet sākotnējos interviju posmus, kas varētu bÅ«t noderÄ«gi tiem, kas ieradās ne tikai klausÄ«ties reportāžas.

Pārskatu tehniskā informācija

Abas dienas klausÄ«jāmies referātus. Brīžiem bija grÅ«ti izvēlēties vienu referātu no paralēlajiem - vienojāmies sadalÄ«ties un apmainÄ«ties ar iegÅ«tajām zināŔanām pārtraukumos. Un pat tā Ŕķiet, ka daudz kas ir izpalikts. Å eit mēs vēlētos runāt par dažu ziņojumu saturu, kas mums Ŕķita visinteresantākie

Izņēmumi valodā C++ caur kompilatoru optimizācijas prizmu, Romāns Rusjajevs

C++ Krievija: kā tas notika
Slaids no ŠæрŠµŠ·ŠµŠ½Ń‚Š°Ń†ŠøŠø

Kā liecina nosaukums, Romāns aplÅ«koja darbu ar izņēmumiem, izmantojot LLVM piemēru. Tajā paŔā laikā tiem, kuri savā darbā neizmanto Clang, pārskats joprojām var sniegt priekÅ”statu par to, kā kodu varētu optimizēt. Tas ir tāpēc, ka kompilatoru un atbilstoÅ”o standarta bibliotēku izstrādātāji sazinās savā starpā un daudzi veiksmÄ«gi risinājumi var sakrist.

Tātad, lai apstrādātu izņēmumu, jums ir jādara daudzas lietas: jāizsauc apstrādes kods (ja tāds ir) vai jāatbrÄ«vo resursi paÅ”reizējā lÄ«menÄ« un jāpalielina steka. Tas viss noved pie tā, ka kompilators pievieno papildu norādÄ«jumus zvaniem, kas potenciāli rada izņēmumus. Tāpēc, ja izņēmums faktiski netiek izvirzÄ«ts, programma joprojām veiks nevajadzÄ«gas darbÄ«bas. Lai kaut kā samazinātu pieskaitāmās izmaksas, LLVM ir vairākas heiristikas, lai noteiktu situācijas, kad izņēmumu apstrādes kods nav jāpievieno vai var samazināt ā€œpapilduā€ instrukciju skaitu.

Runātājs izskata apmēram desmitus no tiem un parāda gan situācijas, kurās tās palÄ«dz paātrināt programmas izpildi, gan tās, kurās Ŕīs metodes nav piemērojamas.

Tādējādi Romāns Rusjajevs liek studentiem secināt, ka kodu, kas satur izņēmumu apstrādi, ne vienmēr var izpildÄ«t ar nulli, un sniedz Ŕādu padomu:

  • attÄ«stot bibliotēkas, principā ir vērts atteikties no izņēmumiem;
  • ja vēl ir vajadzÄ«gi izņēmumi, tad kur vien iespējams ir vērts visur pievienot noexcept (un const) modifikatorus, lai kompilators varētu maksimāli optimizēt.

Kopumā runātājs apstiprināja uzskatu, ka izņēmumus vislabāk izmantot līdz minimumam vai atteikties no tiem vispār.

Pārskatu slaidi ir pieejami Å”ajā saitē: [ā€œC++ izņēmumi, izmantojot LLVM kompilatora optimizācijuā€]

Ģeneratori, korutīnas un citi smadzenes atritinoŔi saldumi, Adi Shavit

C++ Krievija: kā tas notika
Slaids no ŠæрŠµŠ·ŠµŠ½Ń‚Š°Ń†ŠøŠø

Viens no daudzajiem ziņojumiem Å”ajā konferencē, kas bija veltÄ«ts jauninājumiem C++20, bija neaizmirstams ne tikai ar savu krāsaino prezentāciju, bet arÄ« ar skaidru esoÅ”o problēmu identificÄ“Å”anu kolekcijas apstrādes loÄ£ikā (cilpai, atzvanÄ«Å”anai).

Adi Å avits uzsver sekojoÅ”o: paÅ”laik pieejamās metodes iet cauri visai kolekcijai un nenodroÅ”ina piekļuvi kādam iekŔējam starpstāvoklim (vai arÄ« tās nodroÅ”ina atzvanÄ«Å”anas gadÄ«jumā, bet ar lielu skaitu nepatÄ«kamu blakusparādÄ«bu, piemēram, Callback Hell) . Å Ä·iet, ka ir iteratori, bet pat ar tiem viss nav tik gludi: nav kopÄ«gu ieejas un izejas punktu (sākums ā†’ beigas pret rbegin ā†’ rendēt un tā tālāk), nav skaidrs, cik ilgi mēs atkārtosim? Sākot ar C++20, Ŕīs problēmas ir atrisinātas!

Pirmā iespēja: diapazoni. Iesaiņojot iteratorus, mēs iegÅ«stam kopÄ«gu interfeisu iterācijas sākumam un beigām, kā arÄ« iegÅ«stam iespēju komponēt. Tas viss ļauj viegli izveidot pilnvērtÄ«gus datu apstrādes cauruļvadus. Bet ne viss ir tik gluds: daļa aprēķinu loÄ£ikas atrodas konkrēta iteratora ievieÅ”anā, kas var sarežģīt koda izpratni un atkļūdoÅ”anu.

C++ Krievija: kā tas notika
Slaids no ŠæрŠµŠ·ŠµŠ½Ń‚Š°Ń†ŠøŠø

Å ajā gadÄ«jumā C++20 pievienoja korutÄ«nas (funkcijas, kuru darbÄ«ba ir lÄ«dzÄ«ga Python Ä£eneratoriem): izpildi var atlikt, atgriežot kādu paÅ”reizējo vērtÄ«bu, vienlaikus saglabājot starpstāvokli. Tādējādi mēs panākam ne tikai darbu ar datiem, kādi tie parādās, bet arÄ« visas loÄ£ikas iekapsulÄ“Å”anu noteiktā korutÄ«nā.

Bet tur ir muÅ”a: paÅ”laik tos tikai daļēji atbalsta esoÅ”ie kompilatori, kā arÄ« nav ieviesti tik glÄ«ti, kā mēs vēlētos: piemēram, pagaidām nav vērts izmantot atsauces un pagaidu objektus korutÄ«nās. Turklāt ir daži ierobežojumi attiecÄ«bā uz to, kas var bÅ«t korutÄ«nas, un Å”ajā sarakstā nav iekļautas funkcijas constexpr, konstruktori/destruktori un galvenais.

Tādējādi korutÄ«nas atrisina bÅ«tisku daļu problēmu ar datu apstrādes loÄ£ikas vienkārŔību, taču to paÅ”reizējās realizācijas prasa uzlabojumus.

Materiāli:

C++ triki no Yandex.Taxi, Antons Poluhins

Profesionālajā darbÄ«bā man dažreiz ir jāievieÅ” tÄ«ri palÄ«glietas: iesaiņojums starp iekŔējo interfeisu un kādas bibliotēkas API, reÄ£istrÄ“Å”ana vai parsÄ“Å”ana. Å ajā gadÄ«jumā parasti nav nepiecieÅ”ama papildu optimizācija. Bet ko darÄ«t, ja Å”ie komponenti tiek izmantoti dažos populārākajos RuNet pakalpojumos? Šādā situācijā jums bÅ«s jāapstrādā terabaiti stundā vien žurnālu! Tad katra milisekunde ir svarÄ«ga un tāpēc nākas Ä·erties pie dažādiem trikiem ā€“ par tiem stāstÄ«ja Antons Poļuhins.

VarbÅ«t visinteresantākais piemērs bija norādes uz ievieÅ”anu (pimpl) modeļa ievieÅ”ana. 

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

Å ajā piemērā vispirms es vēlos atbrÄ«voties no ārējo bibliotēku galvenes failiem - tas tiks apkopots ātrāk, un jÅ«s varat pasargāt sevi no iespējamiem nosaukumu konfliktiem un citām lÄ«dzÄ«gām kļūdām. 

Labi, mēs pārvietojām #include uz .cpp failu: mums ir nepiecieÅ”ama iesaiņotā API uz priekÅ”u deklarācija, kā arÄ« std::unique_ptr. Tagad mums ir dinamiski pieŔķīrumi un citas nepatÄ«kamas lietas, piemēram, dati, kas izkaisÄ«ti pa daudzām datu kopām, un samazinātas garantijas. std::aligned_storage var palÄ«dzēt ar to visu. 

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

VienÄ«gā problēma: jums ir jānorāda katra iesaiņojuma izmērs un lÄ«dzinājums - izveidosim mÅ«su pimpl veidni ar parametriem , izmantojiet dažas patvaļīgas vērtÄ«bas un pievienojiet destruktoram pārbaudi, vai viss ir pareizi: 

~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ā kā T jau ir definēts, apstrādājot destruktoru, Å”is kods tiks pareizi parsēts un kompilācijas stadijā izvadÄ«s nepiecieÅ”amo izmēru un izlÄ«dzināŔanas vērtÄ«bas, kas jāievada kā kļūdas. Tādējādi uz vienas papildu kompilācijas darbÄ«bas rēķina mēs atbrÄ«vojamies no iesaiņoto klaÅ”u dinamiskās pieŔķirÅ”anas, paslēpjam API .cpp failā ar implementāciju, kā arÄ« iegÅ«stam dizainu, kas ir vairāk piemērots procesora keÅ”atmiņai.

Mežizstrāde un parsÄ“Å”ana Ŕķita mazāk iespaidÄ«ga, tāpēc Å”ajā pārskatā tā netiks pieminēta.

Pārskatu slaidi ir pieejami Å”ajā saitē: ["C++ triki no taksometra"]

MÅ«sdienÄ«gas metodes koda saglabāŔanai SAUSĀ, Bjƶrn Fahller

Šajā runā Bjerns Fahlers parāda vairākus dažādus veidus, kā cīnīties pret atkārtotu stāvokļa pārbaužu stilistiskajiem trūkumiem:

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

Izklausās pazÄ«stami? Izmantojot vairākas jaudÄ«gas C++ tehnikas, kas ieviestas jaunākajos standartos, jÅ«s varat eleganti ieviest to paÅ”u funkcionalitāti bez veiktspējas soda. SalÄ«dzināt:   

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

Lai apstrādātu nefiksētu pārbaužu skaitu, nekavējoties jāizmanto dažādas veidnes un locÄ«Å”anas izteiksmes. Pieņemsim, ka vēlamies pārbaudÄ«t vairāku mainÄ«go vienādÄ«bu ar enum elementu state_type. Pirmā lieta, kas nāk prātā, ir uzrakstÄ«t palÄ«gfunkciju 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 starprezultāts ir neapmierinoŔs. Pagaidām kods nav kļuvis lasāmāks:

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

Netipa veidņu parametri palÄ«dzēs nedaudz uzlabot situāciju. Ar viņu palÄ«dzÄ«bu mēs pārsÅ«tÄ«sim uzskaitāmos enum elementus uz veidnes parametru sarakstu: 

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

Izmantojot auto netipa veidnes parametrā (C++17), pieeja vienkārŔi vispārina salīdzinājumus ne tikai ar state_type elementiem, bet arī ar primitīviem tipiem, kurus var izmantot kā netipa veidnes parametrus:


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

Izmantojot Å”os secÄ«gos uzlabojumus, tiek sasniegta vēlamā plÅ«stoÅ”a pārbaužu sintakse:


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

Å ajā piemērā atskaitÄ«Å”anas rokasgrāmata kalpo, lai kompilatoram ieteiktu vēlamos struktÅ«ras veidnes parametrus, kas zina konstruktora argumentu veidus. 

Tālāk - interesantāk. Bjorns māca, kā iegÅ«to kodu vispārināt salÄ«dzināŔanas operatoriem, kas pārsniedz ==, un pēc tam patvaļīgām darbÄ«bām. Izmantojot lietoÅ”anas piemērus, tiek izskaidrotas tādas funkcijas kā atribÅ«ts no_unique_address (C++20) un veidnes parametri lambda funkcijās (C++20). (Jā, tagad lambda sintakse ir vēl vieglāk iegaumējama - tie ir četri secÄ«gi visu veidu iekavu pāri.) GalÄ«gais risinājums, izmantojot funkcijas kā konstruktora detaļas, patieŔām sasilda manu dvēseli, nemaz nerunājot par izteicienu kortežs labākajās lambda tradÄ«cijās. aprēķins.

Beigās neaizmirstiet to noslīpēt:

  • Atcerieties, ka lambdas ir constexpr bez maksas; 
  • Pievienosim perfektu pārsÅ«tÄ«Å”anu un paskatÄ«simies uz tās neglÄ«to sintaksi saistÄ«bā ar parametru pakotni lambda slēdzenē;
  • Dosim kompilatoram vairāk iespēju optimizācijai ar nosacÄ«jumu noexcept; 
  • ParÅ«pēsimies par saprotamāku kļūdu izvadi veidnēs, pateicoties skaidrām lambdas atgrieÅ”anas vērtÄ«bām. Tas liks kompilatoram veikt vairāk pārbaudes, pirms tiek faktiski izsaukta veidnes funkcija ā€” tipa pārbaudes stadijā. 

SÄ«kāku informāciju skatÄ«t lekciju materiālos: 

MÅ«su iespaidi

MÅ«su pirmā dalÄ«ba C++ Krievijā palika atmiņā ar savu intensitāti. Par C++ Krieviju man radās iespaids kā par sirsnÄ«gu pasākumu, kur robeža starp treniņiem un dzÄ«vo komunikāciju ir gandrÄ«z nemanāma. Viss, sākot no runātāju noskaņojuma un beidzot ar pasākuma partneru konkursiem, veicina asas diskusijas. Konferences saturs, kas sastāv no ziņojumiem, aptver diezgan plaÅ”u tēmu loku, tostarp C++ inovācijas, lielu projektu gadÄ«jumu izpēti un ideoloÄ£iskus arhitektÅ«ras apsvērumus. Taču bÅ«tu negodÄ«gi ignorēt pasākuma sociālo komponentu, kas palÄ«dz pārvarēt valodas barjeras ne tikai attiecÄ«bā uz C++.

Pateicamies konferences organizatoriem par iespēju piedalÄ«ties Ŕādā pasākumā!
Iespējams, esat redzējis organizatoru ierakstu par C++ Krievijas pagātni, tagadni un nākotni JUG Ru emuārā.

Paldies, ka lasījāt, un mēs ceram, ka mūsu notikumu atkārtojums bija noderīgs!

Avots: www.habr.com

Pievieno komentāru