Əgər oyunçunun başlanğıcında divarda C++ kodunun asıldığını söyləsəniz, onun sonunda mütləq sizin ayağınıza atəş açmalıdır.
Bjarne Stroustrup
31-oktyabrdan 1-noyabra qədər Sankt-Peterburqda C++ Rusiyası Piter konfransı keçirilib - Rusiya proqramlaşdırma üzrə ən iri konfranslardan biridir, JUG Ru Group tərəfindən təşkil edilib. Dəvət olunan mühazirəçilər arasında C++ standartlaşdırma komitəsinin üzvləri, CppCon mühazirəçiləri, O'Reilly nəşriyyatının kitab müəllifləri, eləcə də LLVM, libc++ və Boost kimi layihələrin saxlayıcıları var. Konfrans C++ üzrə təcrübəli proqramçılara yönəlib, onlar peşə biliklərini dərinləşdirmək və canlı müzakirələrdə təcrübə mübadiləsi aparmaq istəyirlər. Tələbələr, dissertantlar və universitet müəllimləri üçün xüsusi güzəştlər təqdim edilir.
Moskva konfransının buraxılışını gələn ilin aprelində ziyarət etmək mümkün olacaq, amma hələlik tələbələrimiz keçən tədbirdə nələri öyrəndiklərini paylaşacaqlar.

Fotolar
Haqqımızda
Bu yazıda HSE - Sankt-Peterburq universitetinin iki tələbəsi çalışıb:
- Liza Vasilenko - proqramlaşdırma dilləri ixtisası üzrə 4-cü kurs bakalavr tələbəsi. Universitetin birinci kursunda C++ dili ilə tanış olduqdan sonra, sənayedə praktikalarla ondan istifadə təcrübəsi qazandı. Proqramlaşdırma dillərinə, xüsusən də funksional proqramlaşdırmaya olan marağı konfransda seçilən mühazirələrin üzərində iz buraxdı.
- Danya Smirnov - "Proqramlaşdırma və məlumat analizi" magistraturası üzrə 1-ci kurs tələbəsi. Məktəbdə C++-da olimpiad sualları yazdı, daha sonra bu dil təhsildə davamlı olaraq qarşısına çıxdı və nəticədə əsas iş dili oldu. Konfransda iştirak etməyə qərar verdi ki, biliklərini artırmalı və yeni imkanlar öyrənməlidir.
Fakültə rəhbərliyi tez-tez ixtisasımıza aid təhsil hadisələri ilə bağlı məlumatları paylaşır. Sentyabrda C++ Rusiyası barədə məlumatı gördük və dinləyici kimi qeydiyyatdan keçməyə qərar verdik. Bu, bizdəki belə konfranslarda iştirak etmək üçün ilk təcrübədir.
Konfransın strukturu
Çıxışlar
İki gün ərzində ekspertlər 30 mühazirə təqdim etdilər, bir çox aktual mövzuları müzakirə etdilər: dilin xüsusiyyətlərinin tətbiqi üçün istifadə edilməsi, yeni standartla əlaqədar yaxınlaşan dəyişikliklər, C++ dizaynında kompromislər və onların nəticələri ilə işləyərkən ehtiyat tədbirləri, layihələrin maraqlı arxitekturası üçün nümunələr və dilin arxa planda bəzi texniki detallar. Eyni anda 3 təqdimat keçirildi, adətən ikisi rus dilində, biri isə ingiliscə idi.
Müzakirə bölgələri
Çıxışdan sonra, bütün verilməmiş suallar və tamamlanmamış müzakirələr iştirakçılarla ünsiyyət üçün xüsusi ayrılmış zonasına köçürülürdü, burada marker lövhələri var idi. Xoş söhbət ilə çıxışlar arasında istirahət zamanı vaxt keçirmək üçün yaxşı bir yoldur.
Lightning Talks və qeyri-formal müzakirələr
Qısa bir çıxış etmək istəsəniz, axşam Lightning Talk üçün marker lövhəsində qeyd edə bilərsiniz və konfrans mövzusunda istədiyiniz bir şey barədə beş dəqiqəlik danışığa sahib olarsınız. Məsələn, C++ üçün sanitizatorlara qısa bir giriş (bəzi insanlara yeni oldu) və ya yalnız eşidilə bilən, amma görünməyən sinus dalğası yaradan bir səhv haqqında bir hekayə.
Başqa bir format isə "Ruhlarla Komitə" panel müzakirəsidir. Səhnədə – standartlaşma komitəsinin bəzi üzvləri, projektorda – kamin (rasional olaraq ruhlandırıcı atmosfer yaratmaq üçün, amma "HƏR ŞEY ALAŞADIR" səbəbi daha maraqlı görünür), suallar – standart və C++-a ümumi baxış haqqında, aralarında cəhdli texniki müzakirələr və holivarlar olmadan. Komitədə, bəzi şeylərdə tam güvənməyən və ya nəysə bilməyən real insanlar olduğu ortaya çıxdı.
Mübahisələrə meyilli olanlar üçün üçüncü bir hadisə qaldı – "Go vs C++" BOF-seansı. Go həvəskarı və C++ həvəskarı götürülür, sessiyadan əvvəl birgə 100500 slayd hazırlayırlar (C++-da paketlərin problemləri və ya Go-da genericlərin olmaması kimi məsələlər haqqında) və sonra bir-birləri ilə və auditoriya ilə canlı müzakirə edirlər ki, auditoriya da iki fərqli nöqtəni eyni anda anlamağa çalışır. Mübahisə başlandıqda, moderator müdaxilə edir və tərəfləri barışdırır. Bu format uzanır: saatlarla bir neçə slaydı keçmək oldu, sonunu sürətləndirmək lazım gəldi.
Tərəfdaş stendləri
Hollarda konfransın tərəfdaşları təqdim olundu – stendlərdə cari layihələrdən danışdılar, təcrübələr və iş imkanları təklif etdilər, kvizlər və kiçik yarışmalar keçirdilər, eyni zamanda gözəl hədiyyələr təqdim etdilər. Bəzi şirkətlər hətta ilkin müsahibənin mərhələlərini keçməyi təklif edirdilər ki, bu da məruzələrdən əlavə olaraq gələnlər üçün faydalı ola bilər.
Məruzələrin texniki təfərrüatları
Biz hər iki gün məruzələri dinlədik. Bəzi hallarda eyni anda gedən məruzələrdən birini seçmək çətin olurdu - bölünmək və fasilələrdə əldə olunan bilikləri mübadilə etmək qərarına gəldik. Hətta belə olsa, çox şeyin itirildiyi hiss olunur. Burada biz ən maraqlı məruzələrdən bəzilərinin məzmunu haqqında danışmaq istəyirik.
C++-da istisnaları kompilator optimizasiyaları prizmasından, Roman Rusyaev

Slaid
Adı üzerinde, Roman istisnalarla çalışma konusunu LLVM örneği üzerinden ele aldı. Clang kullanmayanlar için bile, bu sunum kodun nasıl potansiyel olarak optimize edilebileceği hakkında bazı bilgiler sunabiliyor. Bunun nedeni, derleyici geliştiricileri ve ilgili standart kütüphaneler arasında iletişim olmasının yanı sıra, birçok başarılı çözümün örtüşebileceğidir.
Dolayısıyla, bir istisnanın işlenmesi için birçok işlem yapmak gereklidir: işleme kodunu (varsa) çağırmak veya mevcut seviyedeki kaynakları serbest bırakmak ve yığın sarmalamasını yukarı doğru yapmak. Tüm bunlar, potansiyel olarak istisna üretebilecek çağrılar için derleyicinin ek talimatlar eklemesine yol açar. Bu nedenle, eğer bir istisna çağrılmayacaksa, program yine de gereksiz işlemler gerçekleştirecektir. Giderleri azaltmak amacıyla, LLVM'de istisna işleme kodu eklemenin gerekli olmadığı veya 'gereksiz' talimatların sayısını azaltmanın mümkün olduğu durumların belirlenmesi için birkaç sezgi bulunmaktadır.
Sunumcu, bunlardan yaklaşık on tanesini ele almakta ve bu yöntemlerin programın yürütülmesini hızlandırdığı durumları ve bu yöntemlerin uygulanamaz olduğu durumları göstermektedir.
Böylece, Roman Rusyaev dinleyicileri, istisna içeren kodların her zaman sıfır giderle yürütülemeyeceği sonucuna ulaştırmakta ve şu önerilere yer vermektedir:
- kütüphaneler geliştirilirken istisnalardan tamamen kaçınmanız en iyisidir;
- eğer yine de istisnalara ihtiyaç varsa, mümkün olduğunca her yerde noexcept (ve const) başlıklarını eklemelisiniz, böylece derleyici en azından daha fazla optimize edebilir.
Genel olarak, sunumcu istisnaların en az düzeyde kullanılmasının veya tamamen kaçınılmasının en iyi yol olduğu görüşünü doğrulamıştır.
Sunumun slaytları şu bağlantıda mevcuttur:
Generators, coroutines ve diğer beyin açıcı tatlar, Adi Shavit

Slaid
Bu konferansta C++20 yeniliklerine adanmış birçok sunumdan biri, sadece rengarenk hazırlanmış sunumu ile değil, aynı zamanda koleksiyon işlemleri (for döngüsü, callback'ler) ile ilgili mevcut sorunların net bir şekilde tanımlanması ile de akılda kalıyor.
Adi Shavit şu sorunları vurguluyor: mevcut yöntemler koleksiyonu tamamen geçiyor ve bununla birlikte bazı iç ara duruma erişim sağlamıyor (callback'ler durumundayken çok sayıda tatsız yan etki ile birlikte, örneğin Callback Hell). Görünüşte, iteratörler var, ancak onlarla da işler yolunda gitmiyor: ortak bir giriş ve çıkış noktası yok (begin → end karşısında rbegin → rend ve daha fazlası), ne kadar sürede iterasyona devam edeceğimiz belirsiz. C++20 ile birlikte bu sorunlar çözülüyor!
Birinci variant: ranges. Iteratorların üstündəki sarğı sayəsində biz iterasiyanın başlanğıc və sonu üçün ümumi interfeys əldə edirik və eyni zamanda kompozisiya imkanı qazanırıq. Bütün bunlar tam funksional məlumat emalı konveyerləri yaratmağı asanlaşdırır. Amma hər şey belə asan deyil: hesablama məntiqinin bir hissəsi konkret iteratorun içərisində yerləşir, bu da kodun başa düşülməsini və debugging'i çətinləşdirə bilər.

Slaid
Beləliklə, bu halda C++20-də korutinlər əlavə edilmişdir (işləmə davranışı Python dilindəki generatorlara bənzəyir): icra edilməni təxirə salmaq olar, cari dəyəri qaytararaq müvəqqəti vəziyyəti saxlayırıq. Bu sayədə, yalnız məlumatlarla onların ortaya çıxmasıyla işləməkdə deyil, həm də bütün məntiqi konkret korutində kapsulaya bilirik.
Ancaq bir az narahatlıq var: indiki zamanda bunlar var olan kompilyatorlar tərəfindən yalnız qismən dəstəklənir və həmçinin istədiyimiz qədər səliqəli icra edilmir: məsələn, korutinlərdə istinadlar və müvəqqəti obyektləri istifadə etmək tövsiyə edilmir. Üstəlik, korutin edə biləcəkləri haqqında bəzi məhdudiyyətlər var və constexpr funksiyaları, konstruktorlar/destruktorlar və eyni zamanda main bu siyahıya daxil deyil.
Beləliklə, korutinlər, məlumat emalı məntiqinin sadələşdirilməsi ilə bağlı bir çox problemi həll edir, lakin onların cari icra olunması əlavə iş tələb edir.
Materiallar:
- C++ Russia ilə slaydlar —
Yandex.Taksi-dən C++ fəndləri, Anton Poluxin
Peşəkar fəaliyyətimdə bəzən tamamlayıcı şeyləri reallaşdırmaq lazım gəlir: daxili interfeys ilə bir kitabxananın API-si arasında sarğı, logging və ya parsing. Bu zaman adətən əlavə optimizasiya ehtiyacı olmur. Amma bu komponentlər RUnetdəki ən populyar xidmətlərdən birində istifadə olunursa? Belə bir vəziyyətdə yalnız loglardan terabaytları emal etməli olacağıq! O zaman hər bir millisaniyə önəmlidir və buna görə müxtəlif fəndlərə müraciət etməliyik — bunlardan Anton Poluxin danışdı.
Bəlkə də ən maraqlı nümunə, pointer-to-implementation (pimpl) şablonunun reallaşdırılması idi.
#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_;
};Bu nümunədə öncə xarici kitabxanaların başlıq fayllarından xilas olmaq istədim — bu, həm kompilasiyanı sürətləndirəcək, həm də adların toqquşması və digər bənzər səhvlərdən özümüzü qoruyacaq.
Yaxşı, #include-i .cpp-faylına köçürdük: sarılmış API üçün öncədən elan edilməsi və std::unique_ptr lazım oldu. İndi bizdə dinamik ayırmalar və digər narahatedici şeylər, məsələn, xırdalıqların yerdə olması və zəif təminatlar var. Bütün bunların öhdəsindən std::aligned_storage gələ bilər.
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_;
};Təklif olunan yalnız bir problem: hər bir sarğı üçün ölçü və hizalanmanı təyin etmək lazımdır — pimpl-i parametrləri ilə şablonla matris edəcəyik, hansısa təsadüfi dəyərlərlə istifadə edəcəyik və destruktorun içində doğru dəyərləri gözlədiyimizi yoxlayacağıq.
~FastPimpl() noexcept {
validate();
Ptr()->~T();
}
template
static void validate() noexcept {
static_assert(
Size == ActualSize,
"Ölçü və sizeof(T) uyğunsuzdur"
);
static_assert(
Alignment == ActualAlignment,
"Hizalanma və alignof(T) uyğunsuzdur"
);
}Daha doğrusu, destructorda T artıq təyin edildiyi üçün bu kod düzgün şəkildə işləyəcək və kompilyasiya mərhələsində lazımi ölçü və hizalanma dəyərləri ilə relevant xətaları göstərəcəkdir. Beləliklə, bir əlavə kompilyasiya dəfəsi ilə dinamik ayırmağı aradan qaldırırıq, API-nı .cpp faylında reallaşdırılır, həmçinin daha prosessor üçün mükəmməl bir struktur alırıq.
Giriş və parsinq daha az təsirli olduğu üçün bu baxışda qeyd olunmayacaqlar.
Sunumun slaytları şu bağlantıda mevcuttur:
Kodunuzu DRY saxlamağın müasir texnikaları, Björn Fahller
Bu təqdimatda Björn Fahller nəhayət eyni şərtləri təkrar yoxlama problemi ilə mübarizə aparmaq üçün bir neçə fərqli üsul nümayiş etdirir:
assert(a == IDLE || a == CONNECTED || a == DISCONNECTED);Tanışdır? Bir neçə müasir C++ texnikasını istifadə edərək, heç bir performans itkisi olmadan eyni funksionallığı elegant bir şəkildə tətbiq edə bilərsiniz. Müqayisə edin:
assert(a == any_of(IDLE, CONNECTED, DISCONNECTED));Düzgün sayda yoxlamalarla işləmək üçün variadic şablonları və fold ifadələrini istifadə etmək istənə bilər. Tutaq ki, bir neçə dəyişənin enum’dakı state_type ilə bərabərliyini yoxlamaq istəyirik. İlk gələn fikrim — is_any_of adlı köməkçi funksiyanı yazmaqdır:
enum state_type { IDLE, CONNECTED, DISCONNECTED };
template
bool is_any_of(state_type s, const Ts& ... ts) {
return ((s == ts) || ...);
}
Bu aralıq nəticə məyus edir. İndiyə qədər kod daha oxunaqlı olmur:
assert(is_any_of(state, IDLE, DISCONNECTING, DISCONNECTED)); Bir az vəziyyəti düzəltməyə non-type şablon parametrləri kömək edəcək. Bunların köməyi ilə enum’dakı elementləri şablon parametrləri siyahısına köçürəcəyik:
template
bool is_any_of(state_type t) {
return ((t == states) | ...);
}
assert(is_any_of(state)); C++17-də non-type şablon parametrlərində auto istifadə edərək, bu yanaşma state_type elementləri ilə bərabər sadə tiplərlə qarşılaşdırmalara da ümumiləşdirilmiş olur:
template
bool is_any_of(const T& t) {
return ((t == alternatives) | ...);
}Belə ardıcıl təkmilləşdirmələr vasitəsilə yoxlama üçün arzu olunan axıcı sintaksisi əldə edilir:
template
struct any_of : private std::tuple {
// miraculously inherit constructors from 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);
Bu nümunədə deduction guide, strukturun istənilən şablon parametrlərinin təqdimatı üçün kompilatora, konstruktorun arqument növlərini bilən, yardım edir.
Daha maraqlı olacaq. Bjorn müqayisə operatorları üçün (və sonra istənilən əməliyyatlar üçün) alınan kodu ümumiləşdirməyi öyrədir. Eyni zamanda, C++20-dəki no_unique_address attribute və lambda funksiyalarında şablon parametrlərini istifadə etməyi izah edir. (Bəli, indi lambda sintaksisi daha asandır - bu, hər növdən dörd ardıcıl parantez cütüdür.) Nəticə olaraq, konstruktorun detallarından istifadə edən həll mənim üçün çox sevimlidir, tuple ifadəsi isə lambda hesabalamalarının ənənələrinə uyğundur.
Sonda, parıltını unutmayaq:
- Lambdaların - constexpr olduğunu yadıma salaq;
- Perfect forwarding əlavə edəcək və onun lambda bağlamalarda parameter pack-a uyğun çirkin sintaksisini görəcəyik;
- Kompilatoru conditional noexcept ilə optimallaşdırma üçün daha çox imkanlarla təmin edəcəyik;
- Lambda-ların açıq qaytarılan dəyərləri vasitəsilə şablonlardakı xətaların daha aydın çıxışını təmin edəcəyik. Bu, kompilatoru, şablon funksiyasının çağırılmasından əvvəl daha çox yoxlama etməyə məcbur edəcək - növ yoxlama mərhələsində.
Detallara əməliyyatlardan,,,materiallara müraciət edin:
- Slaydlar:
Təəssüratlarimiz
C++ Russia-da ilk iştirakımız zənginliyi ilə xatırlandı. C++ Russia, öyrənmə və canlı ünsiyyət arasında demək olar ki, heç bir sərhədin hiss olunmadığı həssas bir tədbir kimi təsir bağışlayır. Hər şey, iştirakçıların ruhundan, tədbirin tərəfdaşlarının mübarizələrinə qədər, canlı müzakirələrə səbəb olur. Konfransın məzmun hissəsi, C++-taki yenilikləri, iri layihələrdən nümunələr və ideoloji memarlıq baxışlarını əhatə edən geniş bir mövzuları əhatə edir. Ancaq yalnız C++-dan deyil, sosial tərəfi də yaddan çıxarmaq ədalətsiz olardı.
Belə bir hadisədə iştirak imkanı üçün konfransın təşkilatçılarına təşəkkür edirik!
Konfransın təşkilatçılarının keçmiş, indiki və gələcək C++ Russia haqqında yazısını görmüş olmalısınız .
Oxuduğunuz üçün təşəkkür edirik, ümid edirik ki, hadisələrin təsviri sizə faydalı oldu!
Mənbə: habr.com
