C++ Rusija: kako je bilo

Če na začetku igre poveste, da na steni visi koda v C++, potem vam mora proti koncu nujno ustreliti v nogo.

Bjarne Stroustrup

Od 31. oktobra do 1. novembra je v Sankt Peterburgu potekala konferenca C++ Russia Piter – ena največjih konferenc o programiranju v Rusiji, ki jo organizira JUG Ru Group. Med povabljenimi govorniki so člani odbora za standardizacijo C++, predavatelji s CppCon, avtorji knjig založbe O’Reilly ter vzdrževalci projektov, kot so LLVM, libc++ in Boost. Konferenca je usmerjena na izkušene razvijalce v C++, ki želijo poglobiti svoje znanje in izmenjati izkušnje v neposrednem stiku. Študenti, podiplomski študenti in profesorji univerz so deležni zelo prijaznih popustov.

Moskva izdaja konference bo na voljo že aprila naslednje leto, medtem pa naši študenti bodo delili zanimivosti, ki so jih izvedeli na prejšnjem dogodku. 

C++ Rusija: kako je bilo

Fotografija iz albuma konference

O nas

Na tem prispevku sta delala dva študenta NIU VSHE – Sankt Peterburg:

  • Liza Vasilenko – študentka 4. letnika dodiplomskega študija, ki se ukvarja z 'Programskimi jeziki' v okviru programa 'Prikladna matematika in informatika'. Potem ko se je na prvem letniku seznanila z jezikom C++, je kasneje pridobila izkušnje z njim na pripravništvih v industriji. Navdušenje nad programskimi jeziki nasploh in funkcionalnim programiranjem posebej je vplivalo na njen izbor predavanj na konferenci.
  • Danja Smirnov – študent 1. letnika magistrskega študija 'Programiranje in analiza podatkov'. Že v srednji šoli je reševal olimpijske naloge v C++, kasneje pa se je kar nekako zgodilo, da se je jezik neprestano pojavljal v učnih aktivnostih in na koncu postal njegov glavni delovni jezik. Na konferenco se je odločil udeležiti, da bi osvežil svoje znanje in izvedel več o novih možnostih.

V obvestilih fakultete pogosto delijo informacije o izobraževalnih dogodkih, povezanih z našo specializacijo. Septembra smo opazili obvestilo o C++ Russia in se odločili registrirati kot poslušalci. To je naše prvo sodelovanje na takšnih konferencah.

Struktura konference

  • Predstavitve

В течение двух дней экспертизы прочитали 30 докладов, охватив множество актуальных тем: остроумные применения функционала языка для решения практических задач, грядущие обновления языка в свете нового стандарта, компромиссы в дизайне C++ и меры предосторожности при работе с их последствиями, примеры интересной архитектуры проектов, а также некоторые скрытые детали инфраструктуры языка. Одновременно проходило по три выступления, чаще всего два на русском и одно на английском языке.

  • Зоны обсуждений

После выступления все незаданные вопросы и незавершённые дискуссии переносились в специально отведённые зоны общения с докладчиками, оснащённые маркерными досками. Отличный способ провести перерыв между выступлениями за приятным разговором.

  • Молнии и неформальные дискуссии

Если вы хотите сделать короткий доклад — можно записаться на маркерной доске на вечерний Lightning Talk и получить пять минут времени для рассказа о чем угодно по теме конференции. Например, быстрое введение в sanitizers для C++ (для некоторых это оказалось в новинку) или история о баге в генерации синусоиды, который можно только услышать, но не увидеть.

Другой формат — панельная дискуссия «С комитетом по душам». На сцене — некоторые члены комитета по стандартизации, на проекторе — камин (официально — для создания душевной атмосферы, но причина «потому что ВСЁ В ОГНЕ» выглядит забавнее), вопросы — о стандарте и общем видении C++, без бурных технических обсуждений и холиваров. Оказалось, что в комитете тоже есть живые люди, которые в чем-то могут быть не до конца уверены или чего-то не знать.

Для любителей холиваров оставалось третье мероприятие — BOF-сессия «Go против C++». Берем поклонника Go, поклонника C++, перед началом сессии они вместе готовят 100500 слайдов на тему (например, проблемы с пакетами в C++ или отсутствие дженериков в Go), а затем они активно дискутируют между собой и с залом, а зал пытается понять сразу две точки зрения. Если начинается холивар не по делу — вмешивается модератор и примиряет стороны. Такой формат затягивает: через несколько часов после начала пройдена была только половина слайдов. Конец пришлось значительно ускорить.

  • Стенды партнеров

V avlah so bili predstavljeni partnerji konference - na stojnicah so govorili o trenutnih projektih, ponujali prakse in zaposlitev, izvajali kvize in manjša tekmovanja ter podeljevali prijetne nagrade. Pri tem so nekatere podjetja celo ponujala, da se udeležijo začetnih stopenj razgovorov, kar je lahko koristno za tiste, ki niso prišli le poslušat predavanja.

Tehnične podrobnosti predavanj

Slišali smo predavanja oba dni. Včasih je bilo težko izbrati eno predavanje iz tistih, ki so potekala sočasno – dogovorili smo se, da se razdelimo in si izmenjamo pridobljeno znanje med odmori. In tudi tako se zdi, da je ostalo veliko neizkoriščenega. Tukaj bi želeli predstaviti vsebino nekaterih predavanj, ki so se nam zdela najbolj zanimiva.

Izjeme v C++ skozi prizmo optimizacij prevajalnika, Roman Rusejev

C++ Rusija: kako je bilo
Slide iz prezentacije

Kot je razvidno iz naslova, je Roman obravnaval delo z izjemami na primeru LLVM. Kljub temu pa lahko predavanje pri tistih, ki v svojem delu ne uporabljajo Clanga, vseeno ponudi neko predstavo o tem, kako se lahko koda potencialno optimizira. To je tako, ker razvijalci prevajalnikov in sorodnih standardnih knjižnic med seboj komunicirajo, in mnoge uspešne rešitve se lahko ujemajo.

Torej, za obravnavo izjeme je potrebno opraviti vrsto dejanj: poklicati kodo za obravnavo (če obstaja) ali osvoboditi vire na trenutni ravni in razvaliti sklad višje. Vse to vodi do tega, da za potencialno izjavljajoče klice prevajalnik doda dodatne ukaze. Zato, če izjema dejansko ne bo sprožena, bo program vseeno izvajal nepotrebne postopke. Da bi nekako zmanjšali stroške, bo v LLVM več heuristik za ugotavljanje situacij, kjer obravnava izjem ni potrebna ali lahko zmanjša število „odvečnih“ ukazov.

Predavatelj obravnava približno deset jih in prikazuje tako situacije, kjer pomagajo pospešiti izvajanje programa, kot tudi tiste, kjer ti načini niso aplicabilni.

Tako Roman Rusejev slušateljem predaja spoznanje, da kode, ki vsebujejo delo z izjemami, daleč od tega, da bi jih lahko izvajali brez stroškov, in podaja naslednje nasvete:

  • Pri razvoju knjižnic se je treba v osnovi odpovedati izjemam;
  • Če pa so izjemne situacije nujne, bi bilo najbolje povsod dodati modifikatorje noexcept (in const), da bi prevajalnik lahko optimiziral toliko, kolikor lahko.

Na splošno je govornik potrdil mnenje, da je najbolje uporabiti izjeme čim manj ali se jim popolnoma odpovedati.

Slajdi poročila so na voljo na povezavi: [„Izjeme C++ skozi prizmo optimizacij prevajalnika LLVM“]

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

C++ Rusija: kako je bilo
Slide iz prezentacije

Eden izmed mnogih prispevkov te konference, posvečenih novostim C++20, se je zapisal ne le zaradi slikovitih predstavitev, temveč tudi zaradi jasnega opredeljevanja obstoječih težav pri logiki obravnave zbirk (cikel for, callback-i).

Adi Shavit izpostavlja naslednje: trenutne metode obravnavajo zbirko v celoti in pri tem ne nudijo dostopa do nekega notranjega vmesnega stanja (ali pa ga nudijo v primeru callback-ov, vendar z več neprijetnimi stranskimi učinki, kot je t.i. Callback Hell). Zdi se, da obstajajo iterators, vendar ni vse tako preprosto: ni skupne točke vstopa in izstopa (begin → end v primerjavi z rbegin → rend itd.), ni jasno, koliko časa se bomo v resnici ponavljali? Od C++20 se te težave rešujejo!

Prva možnost: ranges. S pomočjo ovijanja okoli iteratorjev dobimo skupni vmesnik za začetek in konec iteracije ter možnost kompozicije. Vse to omogoča enostavno gradnjo polnih cevovodov za obdelavo podatkov. Vendar pa ni vse tako enostavno: del logike izračunov je v sami implementaciji posameznega iteratorja, kar lahko zakomplicira kodo za razumevanje in odpravljanje napak.

C++ Rusija: kako je bilo
Slide iz prezentacije

No, v C++20 so dodane korutine (funkcije, katerih delovanje je podobno generatorjem v jeziku Python): izvajanje lahko odložimo, tako da vrnemo neko trenutno vrednost ob hkratnem shranjevanju vmesnega stanja. Tako dosegamo ne le delo z podatki, ko se le-ti pojavijo, ampak tudi kapsuliramo vso logiko znotraj posamezne korutine.

Vendar je tu žlica katrana: trenutno jih kompilatorji le delno podpirajo in niso implementirani tako skrbno, kot bi si želeli: na primer, zaenkrat ne priporočamo uporabe referenc in začasnih objektov v korutinah. Poleg tega obstajajo nekatere omejitve glede tega, kaj lahko postane korutina, in constexpr funkcije, konstruktorski/kontrolni programi, kot tudi main, ne sodijo v to skupino.

Tako korutine rešujejo precejšen del težav z enostavnostjo obdelave podatkov, vendar njihove trenutne implementacije zahtevajo izboljšave.

Materiali:

C++ triki iz Yandex.Taxi, Anton Poluhin

V svoji profesionalni dejavnosti včasih izvajam čisto pomožne stvari: ovijanje med notranjim vmesnikom in API-jem neke knjižnice, beleženje ali analiziranje. Običajno ni potrebna kakšna dodatna optimizacija. Ampak kaj, če so ti sestavni deli uporabljeni v nekaterih najbolj priljubljenih storitvah v Runetu? V takšni situaciji bo treba obdelati terabajte samo dnevnikov! Takrat je vsaka milisekunda pomembna in zato se je treba zateči k različnim trikom — o tem je govoril Anton Poluhin.

Morda je najbolj zanimiv primer bila implementacija vzorca pointer-to-implementation (pimpl). 

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

V tem primeru si sprva želimo znebiti header datotek zunanjih knjižnic — tako se bo hitreje prevajalo, poleg tega se lahko tudi zaščitimo pred morebitnimi konflikti imen in drugimi podobnimi napakami. 

Dobro, prenesli smo #include v .cpp datoteko: potreben je forward-declaration ovitega API-ja, pa tudi std::unique_ptr. Sedaj imamo dinamične alokacije in druge neprijetne stvari, kot so raztreseni podatki po kupu in zmanjšana jamstva. Vse to lahko pomaga std::aligned_storage. 

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

Edina težava: za vsako ovito strukturo je potrebno določiti velikost in poravnavo — naredimo naš pimpl generičen s parametri , uporabimo ga s kakšnimi poljubnimi vrednostmi in dodamo v destruktor preverjanje, da smo vse pravilno uganili: 

~FastPimpl() noexcept { 
    validate(); 
    Ptr()->~T(); 
}

template 
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-файле с реализацией, а также получаем более подходящую для кеширования процессором структуру.

Логирование и парсинг показались менее интересными, поэтому в данном обзоре они упомянуты не будут.

Slajdi poročila so na voljo na povezavi: [«C++ трюки из Такси»]

Современные техники поддержания вашего кода в стиле DRY, Björn Fahller

В этом докладе Björn Fahller демонстрирует ряд различных способов борьбы с таким стилистическим недостатком, как повторяющиеся проверки условий:

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

Знакомо? Используя несколько мощных техник C++, появившихся в недавних стандартах, можно элегантно реализовать ту же функциональность без малейших потерь в производительности. Сравните:   

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

Для обработки неопределённого числа проверок предложено использовать variadic templates и fold expressions. Предположим, что мы хотим проверить равенство нескольких переменных элементу enum'a state_type. Первое, что приходит на ум — написать вспомогательную функцию is_any_of:


enum state_type { IDLE, CONNECTED, DISCONNECTED };

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

Такой промежуточный результат вызывает разочарование. Пока что код не становится более читаемым:

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

Немного улучшить ситуацию помогут non-type template parameters. С их помощью перенесём перечисляемые элементы enum'a в список параметров шаблона: 

template 
bool is_any_of(state_type t) { 
    return ((t == states) | ...); 
}
	
assert(is_any_of(state)); 

С использованием auto в не типовом параметре шаблона (C++17) подход просто обобщается на сравнения не только с элементами state_type, но и с примитивными типами, которые можно использовать в качестве non-type template parameters:


template 
bool is_any_of(const T& t) {
    return ((t == alternatives) | ...);
}

Takšnih zaporednih izboljšav se doseže želeno tekoče sintaktično preverjanje:


template 
struct any_of : private std::tuple {  
// podedujemo konstruktorje od tuple  
        using std::tuple::tuple;
        template 
        bool operator ==(const T& t) const {
                return std::apply(
                    [&t](const auto& ... ts) {
                            return ((ts == t) || ...);
                    },
                    static_cast<const std::tuple&>(*this));
        }
};

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

V tem primeru vodič za deduciranje služi kot namig za želeno predlogo parametrov strukture za prevajalnik, ki pozna tipe argumentov konstruktorja. 

Nato postane zanimivo. Bjørn uči, kako poenotiti pridobljeno kodo za operacije primerjave poleg ==, nato pa še za poljubne operacije. Ob tem se na primeru uporabe razlagajo funkcionalnosti, kot so no_unique_address attribute (C++20) in predložene parametre v lambda funkcijah (C++20). (Ja, zdaj je sintaksa lambd še lažje zapomniti – to so štiri zaporedne pare okroglih in oglatih okvirov.) Končna rešitev z uporabo funkcij kot delov konstruktorja me osebno močno razveseljuje, še posebej glede izraza tuple v najboljših tradicijah lambda-računanja.

Na koncu ne pozabimo dodati končnega sijaja:

  • Spomnimo se, da so lambde – constexpr brezplačno; 
  • Dodajmo perfect forwarding in si poglejmo njegovo grdoto sintaksa v povezavi z parameter pack v zapiranju lambd;
  • Damo prevajalniku več možnosti za optimizacijo z conditional noexcept; 
  • Poskrbimo za bolj jasno prikazovanje napak v predlogah z jasnimi vrnjenimi vrednostmi lambd. To bo prevajalniku omogočilo več preverjanj pred dejanskim klicem predloge funkcije – v fazi preverjanja tipov. 

Za podrobnosti se obrnite na gradivo predavanja: 

Naši vtisi

Naše prvo učešće u C++ Russia ostalo je upamćeno po svojoj bogatstvu. Stvorio se dojam o C++ Russia kao o duhovnom događaju, gdje je granica između učenja i živog razgovora gotovo neosjetna. Sve, od raspoloženja predavača do takmičenja partnera događaja, potiče na oštre diskusije. Sadržajni deo konferencije, koji obuhvata izlaganja, pokriva prilično širok spektar tema uključujući novitete C++, primere iz prakse velikih projekata i ideološke arhitektonske razmatranja. Ali bi bilo nepravedno ne obratiti pažnju na društvenu komponentu događaja, koja doprinosi prevazilaženju jezičkih barijera ne samo u vezi sa C++.

Zahvaljujemo organizatorima konferencije na mogućnosti da učestvujemo u ovakvom događaju!
Post organizatora o prošlosti, sadašnjosti i budućnosti C++ Russia mogli ste videti na blogu JUG Ru.

Hvala na čitanju, i nadamo se da je naš sažetak događaja bio koristan!

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster