Mendeteksi di C ++ apakah suatu tipe didefinisikan: Memprakarsai hal-hal yang ingin Anda selidiki

Terakhir kali , kami menggunakan SFINAE untuk mendeteksi apakah suatu tipe memiliki definisi, dan kami menggunakannya dalam kombinasi dengan if constexpr dan if constexpr generik sehingga kode dapat menggunakan tipe itu jika didefinisikan, sementara masih diterima oleh kompiler (dan dibuang) ) jika jenisnya tidak ditentukan.

Namun, penggunaan kami memiliki beberapa masalah, beberapa gangguan kecil, beberapa lebih membuat frustrasi.

  • Anda harus mengatakan struct sepanjang waktu.
  • Jika jenisnya tidak ada, tindakan penamaan itu menyebabkan jenis yang akan disuntikkan ke namespace saat ini , bukan namespace tempat Anda mengharapkan tipe tersebut.
  • Anda harus menggunakan teknik struct dengan nama yang tidak memenuhi syarat. Anda tidak dapat menggunakannya untuk menyelidiki tipe yang tidak Anda impor ke namespace saat ini.

Kami dapat memperbaiki ketiga masalah dengan satu solusi: Memprediksi jenis di namespace yang diinginkan.



 // awesome.h namespace awesome { // might or might not contain struct special { ... }; } // your code namespace awesome { // ensure declarations for types we // conditionalize on. struct special; } 

Setelah Anda melakukan ini, Anda tidak perlu mengatakan struct karena struct pasti telah dinyatakan. Penggunaan Anda sebagai parameter tipe templat di call_if_defined tidak akan membuat deklarasi baru, karena sudah dideklarasikan. Dan karena telah dinyatakan, Anda dapat mengaksesnya melalui nama yang tidak memenuhi syarat, nama namespace lengkapnya, atau apa pun di antaranya. Juga tipe alias atau tipe dependen. (Maaf, itu tidak ada di antaranya.)

 namespace app { void foo() { call_if_defined<awesome::special>([&](auto* p) { // this code is compiled only if "awesome::special" // is defined. Create a local name for "special" // by inferring it from the dummy parameter. using special = std::decay_t<decltype(*p)>; // You can now use the local name "special" to access // the features of "awesome::special". special::do_something(); }); } } 

Bagi mereka yang telah mengikuti seri dari awal, Anda mungkin telah memperhatikan bahwa metode call_if_defined tidak cukup sama dengan versi yang kami tulis sebelumnya. Versi baru mendukung beberapa parameter tipe dan memanggil lambda hanya jika semua tipe didefinisikan.

Mari kita lihat lebih dekat:

 template<typename... T, typename TLambda> void call_if_defined(TLambda&& lambda) { if constexpr ((... && is_complete_type_v<T>)) { lambda(static_cast<T*>(nullptr)...); } } 

Tanda kurung ganda di if constexpr ((...)) terlihat aneh, tapi itu wajib. Tanda kurung luar diperlukan oleh pernyataan if constexpr , dan tanda kurung bagian dalam diperlukan oleh ekspresi lipatan . Ekspresi lipatan diperluas ke

  if constexpr ( (is_complete_type_v<T1> && is_complete_type_v<T2> && ... is_complete_type_v<Tn>)) 

Permintaan lambda menggunakan ekspansi paket parameter :

  lambda(static_cast<T*>(nullptr)...); 

Ini berkembang menjadi

  lambda(static_cast<T1*>(nullptr), static_cast<T2*>(nullptr), ..., static_cast<Tn*>(nullptr)); 

di mana static_cast<T*>(nullptr) diulangi sekali untuk setiap jenis.

Seperti yang saya sebutkan sebelumnya, kita dapat menggunakan fungsi ini untuk memanggil lambda jika semua tipe didefinisikan:

 void foo(Source const& source) { call_if_defined<special, magic>( [&](auto* p1, auto* p2) { using special = std::decay_t<decltype(*p1)>; using magic = std::decay_t<decltype(*p2)>; auto s = source.try_get<special>(); if (s) magic::add_magic(s); }); } 

C ++ 20 memungkinkan Anda untuk menulis ini sebagai

 void foo(Source const& source) { call_if_defined<special, magic>( [&]<typename special, typename magic> (special*, magic*) { auto s = source.try_get<special>(); if (s) magic::add_magic(s); }); } 

yang memungkinkan Anda memberi nama jenis templat, dengan demikian menghemat kesulitan karena harus mengembalikannya dengan memainkan std::decay_t games.

Lain kali , kita akan menggunakan ini sebagai batu loncatan dan memperpanjang polanya.



Catatan untuk mereka yang tiba di sini melalui mesin pencari : Ini adalah bagian terakhir dari bagian inti dari seri, tetapi masih ada bagian yang akan datang. Untuk yang tidak sabar, berikut ini hal-hal yang harus disalin-tempel:

 template<typename, typename = void> constexpr bool is_type_complete_v = false; template<typename T> constexpr bool is_type_complete_v <T, std::void_t<decltype(sizeof(T))>> = true; template<typename... T, typename TLambda> void call_if_defined(TLambda&& lambda) { if constexpr ((... && is_complete_type_v<T>)) { lambda(static_cast<T*>(nullptr)...); } } 

Omong-omong, kami memiliki lowongan yang keren [Dublin]


Havok telah menjadi yang terdepan dalam inovasi dalam pengembangan game dan 3D interaktif selama lebih dari satu dekade. Sebagai bagian dari Cognition, tim yang bertanggung jawab atas HoloLens, kami sekarang menggabungkan keahlian itu dengan kekuatan Azure Cloud untuk mengembangkan banyak layanan menarik yang mendorong pengalaman Realita Campuran seperti layanan Azure Remote Rendering yang baru diumumkan. Kami bersemangat tentang konvergensi teknologi AR, VR, dan cloud untuk memungkinkan terciptanya pengalaman Realita Campuran yang memukau.

Bekerja di Havok:

  • Anda akan bekerja dalam tim kecil yang berfokus dengan pengembang berbakat
  • Anda akan memiliki kesempatan untuk bekerja dengan teknologi baru pada beragam platform dan perangkat keras terdepan
  • Anda akan berupaya memecahkan masalah teknis yang menantang dengan cakupan luas
  • Anda akan berkolaborasi dengan tim-tim berbakat di seluruh dunia

Tanggung jawab


  • Desain, kembangkan, uji, dan berikan kode C ++ multiplatform berkualitas tinggi, efisien dan bersih
  • Kembangkan layanan Azure yang sangat skalabel
  • Bekerja secara langsung dengan pelanggan internal dan eksternal untuk mendorong pengembangan produk

Kualifikasi


  • C ++ keterampilan coding dan debugging
  • Kemampuan untuk bekerja di lingkungan tim berdasarkan basis kode bersama
  • Pengalaman dengan teknologi cloud dan layanan terdistribusi (mis. Azure Batch, Azure Blob Storage, Docker, Telemetry)

Poin bonus


Ada banyak keterampilan lain yang tidak diperlukan, tetapi yang berharga di seluruh tim dan ini termasuk:

  • C #, ASP.Net, JavaScript, TypeScript, React
  • Mesin game Unity, Unreal atau terkait
  • Pengalaman dalam 3D, AR, atau VR interaktif
  • Layanan jaringan dan backend
  • Optimalisasi kinerja

Anda dapat memperoleh informasi lebih lanjut dan mengirimkan CV Anda di sini .

Source: https://habr.com/ru/post/id459834/


All Articles