Jika pada awal permainan Anda mengatakan bahwa kode C ++ tergantung di dinding, maka pada akhirnya pasti akan menembak Anda di kaki.
Bjarne Stroustrup
Dari 31 Oktober hingga 1 November, St. Petersburg menjadi tuan rumah Konferensi Piter Rusia C ++ Rusia, salah satu konferensi pemrograman terbesar di Rusia yang diselenggarakan oleh Grup JUG Ru. Di antara pembicara yang diundang adalah anggota komite standardisasi C ++, pembicara dengan CppCon, penulis buku oleh O'Reilly, serta pemelihara proyek seperti LLVM, libc ++ dan Boost. Konferensi ini ditujukan untuk pengembang C ++ berpengalaman yang ingin memperdalam keahlian mereka dan bertukar pengalaman dalam komunikasi langsung. Mahasiswa, mahasiswa pascasarjana dan profesor universitas ditawari diskon yang sangat menyenangkan.
Edisi konferensi Moskow sudah dapat dikunjungi pada bulan April tahun depan, tetapi untuk saat ini siswa kami akan memberi tahu Anda hal-hal menarik apa yang mereka pelajari di acara terakhir.
Foto dari album konferensiTentang kami
Dua siswa dari Sekolah Tinggi Ekonomi - St. Petersburg, mengerjakan pos ini:
- Lisa Vasilenko adalah mahasiswa sarjana tahun ke-4 yang mempelajari arah "Bahasa Pemrograman" sebagai bagian dari program "Matematika Terapan dan Ilmu Komputer". Berkenalan dengan bahasa C ++ di tahun pertama universitas, kemudian memperoleh pengalaman bekerja dengan itu di magang di industri. Semangat untuk bahasa pemrograman pada pemrograman umum dan fungsional khususnya meninggalkan jejak pada pilihan laporan di konferensi.
- Danya Smirnov adalah siswa tahun pertama dari program master "Pemrograman Data dan Analisis". Ketika masih di sekolah, ia menulis masalah Olimpiade di C ++, dan kemudian entah bagaimana bahasa itu terus muncul dalam kegiatan pendidikan dan sebagai hasilnya menjadi yang bekerja utama. Saya memutuskan untuk berpartisipasi dalam konferensi untuk meningkatkan pengetahuan saya, serta belajar tentang peluang baru.
Dalam buletin, para pemimpin fakultas sering berbagi informasi tentang acara-acara pendidikan yang berkaitan dengan spesialisasi kami. Pada bulan September, kami melihat informasi tentang C ++ Rusia dan memutuskan untuk mendaftar sebagai pendengar. Ini adalah pengalaman pertama kami berpartisipasi dalam konferensi semacam itu.
Struktur Konferensi
Selama dua hari, para ahli membaca 30 laporan yang menyoroti banyak topik hangat: aplikasi cerdas fitur bahasa untuk menyelesaikan masalah yang diterapkan, pembaruan bahasa mendatang karena standar baru, kompromi dalam desain C ++ dan tindakan pencegahan ketika bekerja dengan konsekuensinya, contoh arsitektur proyek yang menarik, serta beberapa bagian mesin dari infrastruktur bahasa. Pada saat yang sama, 3 pertunjukan berlangsung, paling sering dua dalam bahasa Rusia dan satu dalam bahasa Inggris.
Setelah pidato tersebut, semua pertanyaan yang tidak terjawab dan diskusi tidak lengkap dipindahkan ke area komunikasi yang dirancang khusus dengan pembicara yang dilengkapi dengan papan penanda. Cara yang baik untuk melewati jeda antara pertunjukan untuk percakapan yang menyenangkan.
Pembicaraan Petir dan diskusi informal
Jika Anda ingin membuat laporan singkat, Anda dapat mendaftar untuk Petir Talk malam di papan penanda dan mendapatkan lima menit waktu untuk berbicara tentang apa pun tentang topik konferensi. Misalnya, pengantar cepat pembersih untuk C ++ (yang ternyata baru bagi sebagian orang) atau cerita tentang bug pada generasi sinusoid yang hanya bisa Anda dengar tetapi tidak dilihat.
Format lain adalah diskusi panel “With the Soul Committee”. Di atas panggung ada beberapa anggota komite standardisasi, di proyektor ada perapian (secara resmi - untuk menciptakan suasana yang penuh perasaan, tetapi alasan "karena SEMUANYA KEBAKARAN" tampaknya lebih lucu), pertanyaannya adalah tentang visi standar dan umum dari C ++, tanpa diskusi teknis dan holivar yang dipanaskan. Ternyata orang yang masih hidup juga duduk di komite, yang mungkin tidak sepenuhnya yakin akan sesuatu atau mungkin tidak tahu sesuatu.
Untuk penggemar holivar, acara ketiga tetap - sesi BOF "Go menentang C ++". Kami mengambil kekasih Go, kekasih C ++, sebelum memulai sesi, mereka menyiapkan 100500 slide pada topik bersama-sama (seperti masalah dengan paket dalam C ++ atau kurangnya obat generik di Go), dan kemudian mereka dengan bersemangat membahas antara mereka sendiri dan audiens, dan audiens mencoba memahami dua sudut pandang sekaligus. . Jika holivar tidak memulai bisnis, moderator mengintervensi dan merekonsiliasi para pihak. Format ini membuat ketagihan: beberapa jam setelah dimulainya, hanya setengah dari slide yang selesai. Akhirnya harus dipercepat.
Mitra konferensi diwakili di aula - mereka berbicara tentang proyek saat ini di stan, menawarkan magang dan pekerjaan, mengadakan kuis dan kompetisi kecil, dan juga memainkan hadiah bagus. Namun, beberapa perusahaan bahkan menawarkan untuk melalui tahap awal wawancara, yang mungkin berguna bagi mereka yang datang tidak hanya untuk mendengarkan laporan.
Detail teknis dari laporan
Kami mendengarkan laporan dua hari. Terkadang sulit untuk memilih satu laporan dari yang berjalan secara paralel - kami sepakat untuk berbagi dan bertukar pengetahuan yang diperoleh selama istirahat. Meski begitu, tampaknya banyak yang hilang. Di sini kami ingin berbicara tentang konten beberapa laporan yang menurut kami paling menarik
Pengecualian dalam C ++ melalui prisma optimasi kompiler, Roman Rusyaev
Slide presentasiSeperti namanya, Roman melihat bekerja dengan pengecualian menggunakan LLVM sebagai contoh. Pada saat yang sama, bagi mereka yang tidak menggunakan dentang dalam pekerjaan mereka, laporan tersebut masih dapat memberikan beberapa gagasan tentang bagaimana kode berpotensi dioptimalkan. Ini karena pengembang kompiler dan pustaka standar yang sesuai berkomunikasi satu sama lain dan banyak solusi yang berhasil mungkin bersamaan.
Jadi, untuk menangani pengecualian, Anda perlu melakukan banyak tindakan: hubungi kode pemrosesan (jika ada) atau membebaskan sumber daya di level saat ini dan melepas tumpukan lebih tinggi. Semua ini mengarah pada fakta bahwa kompiler menambahkan instruksi tambahan untuk berpotensi melakukan panggilan. Oleh karena itu, jika pengecualian pada kenyataannya tidak disebabkan, program masih akan mulai melakukan tindakan yang tidak perlu. Untuk mengurangi biaya overhead, LLVM memiliki beberapa heuristik untuk menentukan situasi di mana Anda tidak perlu menambahkan kode penanganan pengecualian atau Anda dapat mengurangi jumlah instruksi "yang tidak perlu".
Pembicara mempertimbangkan sekitar selusin dari mereka dan menunjukkan kedua situasi di mana mereka membantu mempercepat pelaksanaan program, dan situasi di mana metode ini tidak berlaku.
Dengan demikian, Roman Rusyaev mengarahkan audiens ke kesimpulan bahwa kode yang berisi pekerjaan dengan pengecualian tidak dapat selalu dieksekusi dengan overhead nol, dan memberikan tips berikut:
- saat mengembangkan perpustakaan, Anda harus meninggalkan pengecualian pada prinsipnya;
- jika Anda masih membutuhkan pengecualian, maka sedapat mungkin ada baiknya menambahkan pengubah noexcept (dan const) sehingga kompiler dapat mengoptimalkan sebanyak mungkin.
Secara umum, pembicara menegaskan kembali pandangan bahwa pengecualian paling baik digunakan untuk minimum, atau bahkan meninggalkannya.
Slide laporan tersedia di:
[“C ++ Pengecualian Melalui Prisma Optimalisasi Kompiler LLVM”]Generator, coroutine, dan rasa manis tak terkendali lainnya di otak, Adi Shavit
Slide presentasiSalah satu dari banyak laporan konferensi ini yang ditujukan untuk inovasi C ++ 20 diingat tidak hanya oleh presentasi yang disajikan dengan penuh warna, tetapi juga oleh penunjukan yang jelas dari masalah yang ada dengan logika pemrosesan koleksi (untuk, loop panggilan balik).
Adi Shavit menyoroti hal-hal berikut: metode yang saat ini tersedia melewati seluruh koleksi dan tidak memberikan akses ke beberapa kondisi perantara internal (atau memberi dalam hal panggilan balik, tetapi dengan banyak efek samping yang tidak menyenangkan, seperti Neraka Panggilan Balik yang sama). Tampaknya ada iterator, tetapi semuanya tidak begitu mulus dengan mereka: tidak ada titik masuk dan keluar yang umum (mulai → akhir versus rbegin → rend dan seterusnya), tidak jelas berapa banyak yang akan kita ulangi sama sekali? Dimulai dengan C ++ 20, masalah ini terpecahkan!
Opsi pertama: rentang. Karena pembungkus di atas iterator, kami mendapatkan antarmuka umum untuk awal dan akhir iterasi, serta kemungkinan komposisi. Semua ini membuatnya mudah untuk membangun jaringan pipa pemrosesan data yang lengkap. Tetapi tidak semuanya begitu lancar: bagian dari logika perhitungan ada di dalam implementasi iterator tertentu, yang dapat menyulitkan kode untuk persepsi dan debugging.
Slide presentasiNah, untuk kasus ini, coroutine ditambahkan dalam C ++ 20 (fungsi yang perilakunya mirip dengan generator di Python): eksekusi dapat ditunda dengan mengembalikan beberapa nilai saat ini sambil mempertahankan keadaan menengah. Dengan demikian, kami mencapai tidak hanya bekerja dengan data saat mereka muncul, tetapi juga merangkum semua logika di dalam coroutine tertentu.
Tetapi ada lalat di salep: saat ini mereka hanya didukung sebagian oleh kompiler yang ada, dan mereka juga tidak diimplementasikan seakurat yang kita inginkan: misalnya, tautan dan benda sementara tidak boleh digunakan di coroutine. Plus, ada beberapa batasan pada apa yang bisa menjadi coroutine, dan fungsi constexpr, konstruktor / destruktor, dan juga utama tidak termasuk dalam daftar ini.
Dengan demikian, coroutine memecahkan sebagian besar masalah dengan kesederhanaan logika pemrosesan data, tetapi implementasinya saat ini membutuhkan perbaikan.
Bahan:
Trik C ++ dari Yandex.Taxi, Anton Polukhin
Dalam aktivitas profesionalnya, kadang-kadang Anda harus menerapkan hal-hal tambahan murni: pembungkus antara antarmuka internal dan API dari beberapa perpustakaan, masuk atau parsing. Namun, biasanya tidak perlu untuk optimasi tambahan. Tetapi bagaimana jika komponen-komponen ini digunakan di beberapa layanan paling populer di Runet? Dalam situasi seperti itu, Anda harus memproses terabyte per jam dari log saja! Kemudian setiap milidetik berarti dan karena itu Anda harus menggunakan berbagai trik - Anton Polukhin berbicara tentang mereka.
Mungkin contoh yang paling menarik adalah penerapan pola pointer-to-implementasi (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_; };
Dalam contoh ini, pertama Anda ingin menyingkirkan file header perpustakaan eksternal - itu akan mengkompilasi lebih cepat, dan Anda dapat melindungi diri dari kemungkinan konflik nama dan kesalahan serupa lainnya.
Oke, pindahkan #sertakan ke file .cpp: Anda memerlukan deklarasi maju dari API yang dibungkus, serta std :: unique_ptr. Sekarang kami memiliki alokasi dinamis dan hal-hal tidak menyenangkan lainnya, seperti data yang tersebar di tumpukan dan mengurangi jaminan. Dengan semua ini, std :: aligned_storage dapat membantu.
struct Value {
Satu-satunya masalah: Anda perlu menentukan ukuran dan perataan untuk setiap bungkus - kami akan membuat template jerawat kami dengan parameter <T, SizeT, AlignmentT>, menggunakan beberapa nilai arbitrer dan menambahkan ke destructor tanda centang yang kami tebak semuanya:
~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" ); }
Karena T sudah didefinisikan selama pemrosesan destruktor, kode ini akan diuraikan dengan benar dan pada tahap kompilasi, kode ini akan menampilkan ukuran dan nilai perataan yang diperlukan yang perlu dimasukkan dalam bentuk kesalahan. Jadi, dengan mengorbankan satu awal tambahan kompilasi, kami menyingkirkan alokasi dinamis dari kelas yang dibungkus, menyembunyikan API dalam file .cpp dengan implementasinya, dan juga mendapatkan desain yang lebih cocok untuk caching oleh prosesor.
Penebangan dan penguraian tampak kurang mengesankan, dan karenanya tidak akan disebutkan dalam ulasan ini.
Slide laporan tersedia di tautan:
[“Trik Taksi C ++”]Teknik modern untuk menjaga kode Anda KERING, Björn Fahller
Dalam ceramah ini, Björn Fahller menunjukkan beberapa cara berbeda untuk menangani kekurangan gaya bahasa seperti pemeriksaan bersyarat berulang:
assert(a == IDLE || a == CONNECTED || a == DISCONNECTED);
Apakah itu familier? Menggunakan beberapa teknik C ++ yang kuat yang telah muncul dalam standar terbaru, Anda dapat mengimplementasikan fungsi yang sama dengan anggun tanpa kehilangan kinerja sedikit pun. Bandingkan:
assert(a == any_of(IDLE, CONNECTED, DISCONNECTED));
Untuk memproses jumlah cek yang tidak terbatas, Anda segera diminta untuk menggunakan templat variadic dan melipat ekspresi. Misalkan kita ingin memeriksa kesetaraan beberapa variabel ke elemen enum'a state_type. Hal pertama yang terlintas dalam pikiran adalah untuk menulis fungsi pembantu 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) || ...); }
Hasil antara seperti itu mengecewakan. Sejauh ini, kode tidak dapat dibaca:
assert(is_any_of(state, IDLE, DISCONNECTING, DISCONNECTED));
Parameter template non-tipe akan membantu sedikit memperbaiki situasi. Dengan bantuan mereka, kami mentransfer elemen enum enumerasi ke daftar parameter template:
template <state_type ... states> bool is_any_of(state_type t) { return ((t == states) | ...); } assert(is_any_of<IDLE, DISCONNECTING, DISCONNECTED>(state));
Menggunakan otomatis dalam parameter template non-tipikal (C ++ 17), pendekatan ini hanya digeneralisasikan untuk perbandingan tidak hanya dengan elemen state_type, tetapi juga dengan tipe primitif yang dapat digunakan sebagai parameter template non-tipe:
template <auto ... alternatives, typename T> bool is_any_of(const T& t) { return ((t == alternatives) | ...); }
Melalui peningkatan bertahap ini, sintaksis sepintas yang diinginkan untuk pemeriksaan tercapai:
template <class ... Ts> struct any_of : private std::tuple<Ts ...> {
Dalam contoh ini, panduan deduksi berfungsi untuk meminta parameter struktur template yang diinginkan ke kompiler yang mengetahui tipe argumen konstruktor.
Lebih menarik. Bjorn mengajarkan untuk menggeneralisasi kode yang dihasilkan untuk operator perbandingan selain ==, dan kemudian untuk operasi sewenang-wenang. Seiring dengan use case, fitur-fitur seperti atribut no_unique_address (C ++ 20) dan parameter template dalam fungsi lambda (C ++ 20) dijelaskan. (Ya, sekarang sintaks lambda bahkan lebih mudah diingat - ini adalah empat pasang kurung berturut-turut dari semua jenis.) Solusi terakhir menggunakan fungsi sebagai bagian konstruktor benar-benar menghangatkan jiwa saya, belum lagi ekspresi tuple dalam tradisi terbaik kalkulus lambda.
Pada akhirnya, jangan lupa untuk membuat gloss:
- Ingat bahwa lambda adalah constexpr gratis;
- Tambahkan penerusan sempurna dan lihat sintaks jeleknya sebagaimana diterapkan pada paket parameter pada penutupan lambda;
- Mari kita beri kompiler lebih banyak opsi untuk optimisasi dengan conditional noexcept;
- Kami akan menangani output kesalahan yang lebih jelas dalam templat karena nilai pengembalian lambda yang eksplisit. Ini akan memaksa kompiler untuk melakukan lebih banyak pemeriksaan sebelum benar-benar memanggil fungsi template - pada tahap pengecekan tipe.
Untuk perincian, lihat materi kuliah:
Tayangan kami
Partisipasi pertama kami di C ++ Rusia dikenang karena kekayaannya. Ada kesan C ++ Rusia sebagai peristiwa emosional, di mana garis antara belajar dan komunikasi langsung hampir tidak terlihat. Semuanya, mulai dari suasana hati para pembicara hingga kompetisi dari para mitra acara, kondusif untuk diskusi yang memanas. Isi konferensi, yang terdiri dari laporan, mencakup berbagai topik yang cukup luas, termasuk inovasi C ++, contoh-contoh dari praktik proyek besar, dan pertimbangan arsitektur ideologis. Tetapi akan tidak adil untuk menghilangkan perhatian dari komponen sosial dari acara tersebut, yang membantu untuk mengatasi hambatan bahasa sehubungan dengan tidak hanya C ++.
Kami berterima kasih kepada penyelenggara konferensi atas kesempatan untuk berpartisipasi dalam acara semacam itu!
Anda bisa melihat posting penyelenggara tentang masa lalu, sekarang, dan masa depan C ++ Rusia
di blog JUG Ru .
Terima kasih telah membaca, dan kami berharap menceritakan kembali acara kami ternyata bermanfaat!