C++ รัสเซีย: มันเกิดขึ้นได้อย่างไร

หากตอนเริ่มเล่นคุณบอกว่ามีโค้ด C++ แขวนอยู่บนผนัง ตอนจบเกมจะต้องยิงคุณให้ตาย

บียาร์น สตรุสตรัป

ตั้งแต่วันที่ 31 ตุลาคมถึง 1 พฤศจิกายน การประชุม C++ Russia Piter จัดขึ้นที่เซนต์ปีเตอร์สเบิร์ก ซึ่งเป็นหนึ่งในการประชุมการเขียนโปรแกรมขนาดใหญ่ในรัสเซีย ซึ่งจัดโดย JUG Ru Group วิทยากรรับเชิญประกอบด้วยสมาชิกของคณะกรรมการมาตรฐาน C++, วิทยากร CppCon, ผู้เขียนหนังสือ O'Reilly และผู้ดูแลโครงการ เช่น LLVM, libc++ และ Boost การประชุมนี้มุ่งเป้าไปที่นักพัฒนา C++ ที่มีประสบการณ์ ซึ่งต้องการเพิ่มพูนความเชี่ยวชาญและแลกเปลี่ยนประสบการณ์ในการสื่อสารสด นักศึกษา นักศึกษาระดับบัณฑิตศึกษา และอาจารย์มหาวิทยาลัยจะได้รับส่วนลดสุดพิเศษ

การประชุมฉบับที่มอสโกจะเปิดให้เข้าชมได้เร็วที่สุดในเดือนเมษายนปีหน้า แต่ในระหว่างนี้ นักเรียนของเราจะเล่าให้คุณฟังถึงสิ่งที่น่าสนใจที่พวกเขาได้เรียนรู้จากงานครั้งล่าสุด 

C++ รัสเซีย: มันเกิดขึ้นได้อย่างไร

ภาพจาก อัลบั้มการประชุม

เกี่ยวกับเรา

นักศึกษาสองคนจาก National Research University Higher School of Economics - เซนต์ปีเตอร์สเบิร์กทำงานในโพสต์นี้:

  • Liza Vasilenko เป็นนักศึกษาระดับปริญญาตรีชั้นปีที่ 4 ที่กำลังศึกษาภาษาการเขียนโปรแกรมซึ่งเป็นส่วนหนึ่งของโปรแกรมคณิตศาสตร์ประยุกต์และวิทยาการคอมพิวเตอร์ หลังจากที่ฉันคุ้นเคยกับภาษา C++ ในปีแรกที่มหาวิทยาลัย ฉันก็ได้รับประสบการณ์ในการทำงานกับภาษานี้ผ่านการฝึกงานในอุตสาหกรรมนี้ ความหลงใหลในการเขียนโปรแกรมภาษาทั่วไปและการเขียนโปรแกรมเชิงฟังก์ชันโดยเฉพาะได้ทิ้งร่องรอยไว้ในการเลือกรายงานในการประชุม
  • Danya Smirnov เป็นนักศึกษาชั้นปีที่ 1 ของหลักสูตรปริญญาโท "การเขียนโปรแกรมและการวิเคราะห์ข้อมูล" ตอนที่ยังเรียนอยู่ที่โรงเรียน ฉันเขียนโจทย์ปัญหาโอลิมปิกด้วยภาษา C++ แต่แล้วภาษานั้นก็เข้ามามีบทบาทในกิจกรรมด้านการศึกษาอยู่ตลอดเวลา และในที่สุดก็กลายเป็นภาษาหลักในการทำงาน ฉันตัดสินใจเข้าร่วมการประชุมเพื่อพัฒนาความรู้และเรียนรู้เกี่ยวกับโอกาสใหม่ๆ

ในจดหมายข่าว ผู้นำคณะมักจะแบ่งปันข้อมูลเกี่ยวกับกิจกรรมการศึกษาที่เกี่ยวข้องกับความเชี่ยวชาญพิเศษของเรา ในเดือนกันยายน เราเห็นข้อมูลเกี่ยวกับ C++ Russia และตัดสินใจลงทะเบียนเป็นผู้ฟัง นี่เป็นประสบการณ์ครั้งแรกของเราในการเข้าร่วมการประชุมดังกล่าว

โครงสร้างการประชุม

  • รายงาน

ตลอดระยะเวลาสองวัน ผู้เชี่ยวชาญอ่านรายงาน 30 ฉบับ ครอบคลุมหัวข้อยอดนิยมมากมาย: การใช้ฟีเจอร์ภาษาอย่างชาญฉลาดเพื่อแก้ไขปัญหาที่นำไปใช้ การอัปเดตภาษาที่กำลังจะเกิดขึ้นซึ่งเกี่ยวข้องกับมาตรฐานใหม่ การประนีประนอมในการออกแบบ C++ และข้อควรระวังเมื่อทำงานกับผลที่ตามมา ตัวอย่าง ของสถาปัตยกรรมโปรเจ็กต์ที่น่าสนใจ รวมถึงรายละเอียดเบื้องหลังบางประการของโครงสร้างพื้นฐานทางภาษา การแสดงสามครั้งเกิดขึ้นพร้อมกัน ส่วนใหญ่เป็นภาษารัสเซียสองรายการและภาษาอังกฤษอีกหนึ่งรายการ

  • โซนสนทนา

หลังจากการกล่าวสุนทรพจน์ คำถามที่ยังไม่ได้ถามและการสนทนาที่ยังไม่เสร็จสิ้นทั้งหมดจะถูกโอนไปยังพื้นที่ที่กำหนดไว้เป็นพิเศษสำหรับการสื่อสารกับวิทยากร ซึ่งมีกระดานทำเครื่องหมาย วิธีที่ดีในการหยุดพักระหว่างการกล่าวสุนทรพจน์ด้วยการสนทนาที่น่ารื่นรมย์

  • Lightning Talks และการอภิปรายอย่างไม่เป็นทางการ

หากคุณต้องการรายงานสั้นๆ คุณสามารถลงทะเบียนบนไวท์บอร์ดสำหรับ Lightning Talk ตอนเย็น และมีเวลาห้านาทีเพื่อพูดคุยเกี่ยวกับอะไรก็ได้ในหัวข้อการประชุม ตัวอย่างเช่น การแนะนำสั้นๆ เกี่ยวกับน้ำยาฆ่าเชื้อสำหรับภาษา C++ (สำหรับบางรุ่นเป็นเรื่องใหม่) หรือเรื่องราวเกี่ยวกับจุดบกพร่องในการสร้างคลื่นไซน์ที่ได้ยินแต่มองไม่เห็น

อีกรูปแบบหนึ่งคือเสวนา “ด้วยคณะกรรมการหัวใจต่อหัวใจ” บนเวทีมีสมาชิกคณะกรรมการกำหนดมาตรฐานบางคนบนโปรเจ็กเตอร์คือเตาผิง (อย่างเป็นทางการ - เพื่อสร้างบรรยากาศที่จริงใจ แต่เหตุผลที่ "เพราะทุกอย่างลุกเป็นไฟ" ดูน่าสนุกกว่า) คำถามเกี่ยวกับมาตรฐานและวิสัยทัศน์ทั่วไปของ C ++ โดยไม่มีการอภิปรายทางเทคนิคและโฮลีวอร์อย่างเผ็ดร้อน ปรากฎว่าคณะกรรมการยังมีคนที่ยังมีชีวิตอยู่ซึ่งอาจไม่แน่ใจในบางสิ่งบางอย่างหรืออาจไม่รู้อะไรบางอย่าง

สำหรับผู้ชื่นชอบ Holivars งานที่สามยังคงอยู่สำหรับเคสนี้ - เซสชั่น BOF “Go vs. C++” เราพาคนรัก Go ซึ่งเป็นคนรัก C++ ก่อนเริ่มเซสชั่น พวกเขาร่วมกันเตรียมสไลด์ 100500 สไลด์ในหัวข้อหนึ่ง (เช่น ปัญหาเกี่ยวกับแพ็คเกจในภาษา C++ หรือการขาดข้อมูลทั่วไปใน Go) จากนั้นพวกเขาก็พูดคุยกันอย่างมีชีวิตชีวาระหว่างกันและ กับผู้ชม และผู้ชมพยายามทำความเข้าใจสองมุมมองพร้อมกัน หากโฮลิวาร์เริ่มต้นโดยไม่มีบริบท ผู้ดำเนินรายการจะเข้ามาแทรกแซงและปรับทั้งสองฝ่าย รูปแบบนี้น่าดึงดูดใจ หลังจากผ่านไปหลายชั่วโมงหลังจากเริ่มต้น มีสไลด์เพียงครึ่งเดียวเท่านั้นที่เสร็จสมบูรณ์ การสิ้นสุดจะต้องเร่งอย่างมาก

  • พันธมิตรยืน

พันธมิตรของการประชุมเป็นตัวแทนในห้องโถง - พวกเขาพูดคุยเกี่ยวกับโครงการปัจจุบันที่อัฒจันทร์ เสนอการฝึกงานและการจ้างงาน จัดแบบทดสอบและการแข่งขันขนาดเล็ก และยังจับฉลากรางวัลดีๆ อีกด้วย ในเวลาเดียวกัน บางบริษัทถึงกับเสนอให้ผ่านขั้นตอนแรกของการสัมภาษณ์ ซึ่งอาจเป็นประโยชน์สำหรับผู้ที่มาไม่เพียงแต่เพื่อฟังรายงานเท่านั้น

รายละเอียดทางเทคนิคของรายงาน

เราฟังรายงานทั้งสองวัน บางครั้งการเลือกรายงานหนึ่งฉบับจากรายงานคู่ขนานก็เป็นเรื่องยาก เราตกลงที่จะแยกและแลกเปลี่ยนความรู้ที่ได้รับระหว่างช่วงพัก และถึงอย่างนั้นก็ดูเหมือนว่าจะยังเหลืออยู่มาก ที่นี่เราอยากจะพูดคุยเกี่ยวกับเนื้อหาของรายงานบางส่วนที่เราพบว่าน่าสนใจที่สุด

ข้อยกเว้นในภาษา C++ ผ่านปริซึมของการเพิ่มประสิทธิภาพคอมไพเลอร์ Roman Rusyaev

C++ รัสเซีย: มันเกิดขึ้นได้อย่างไร
เลื่อนจาก การนำเสนอผลงาน

ตามชื่อเรื่อง Roman ดูการทำงานโดยมีข้อยกเว้นโดยใช้ LLVM เป็นตัวอย่าง ในขณะเดียวกัน สำหรับผู้ที่ไม่ได้ใช้ Clang ในการทำงาน รายงานยังสามารถให้แนวคิดบางประการว่าโค้ดสามารถเพิ่มประสิทธิภาพได้อย่างไร ที่เป็นเช่นนี้เพราะนักพัฒนาคอมไพเลอร์และไลบรารีมาตรฐานที่เกี่ยวข้องสื่อสารกัน และโซลูชันที่ประสบความสำเร็จมากมายก็อาจเกิดขึ้นพร้อมกันได้

ดังนั้นเพื่อจัดการกับข้อยกเว้น คุณต้องทำหลายสิ่งหลายอย่าง: เรียกโค้ดการจัดการ (ถ้ามี) หรือทรัพยากรว่างในระดับปัจจุบันและหมุนสแต็กให้สูงขึ้น ทั้งหมดนี้นำไปสู่ความจริงที่ว่าคอมไพเลอร์เพิ่มคำแนะนำเพิ่มเติมสำหรับการเรียกที่อาจทำให้เกิดข้อยกเว้น ดังนั้นหากไม่มีข้อยกเว้นเกิดขึ้นจริง โปรแกรมจะยังคงดำเนินการที่ไม่จำเป็น เพื่อลดค่าใช้จ่าย LLVM มีการวิเคราะห์พฤติกรรมหลายประการในการกำหนดสถานการณ์ที่ไม่จำเป็นต้องเพิ่มโค้ดการจัดการข้อยกเว้นหรือจำนวนคำสั่ง "พิเศษ" สามารถลดลงได้

ผู้บรรยายจะตรวจสอบสถานการณ์เหล่านี้ประมาณโหลและแสดงให้เห็นทั้งสองสถานการณ์ที่ช่วยเร่งการทำงานของโปรแกรม และสถานการณ์ที่ไม่สามารถใช้วิธีการเหล่านี้ได้

ดังนั้น Roman Rusyaev จึงนำนักเรียนไปสู่ข้อสรุปว่าโค้ดที่มีการจัดการข้อยกเว้นไม่สามารถดำเนินการได้โดยมีค่าใช้จ่ายเป็นศูนย์เสมอไป และให้คำแนะนำต่อไปนี้:

  • เมื่อพัฒนาห้องสมุดควรละทิ้งข้อยกเว้นตามหลักการ
  • หากยังจำเป็นต้องมีข้อยกเว้น เมื่อใดก็ตามที่เป็นไปได้ ก็ควรเพิ่มตัวแก้ไข noException (และ const) ทุกที่ เพื่อให้คอมไพเลอร์สามารถปรับให้เหมาะสมได้มากที่สุด

โดยทั่วไป ผู้บรรยายยืนยันมุมมองว่าข้อยกเว้นควรใช้ให้น้อยที่สุดหรือละทิ้งไปโดยสิ้นเชิง

สไลด์รายงานมีอยู่ที่ลิงค์ต่อไปนี้: [“ข้อยกเว้น C++ ผ่านเลนส์ของการเพิ่มประสิทธิภาพคอมไพเลอร์ LLVM”]

เครื่องกำเนิด โครูทีน และความหวานที่ทำให้สมองปลอดโปร่ง Adi Shavit

C++ รัสเซีย: มันเกิดขึ้นได้อย่างไร
เลื่อนจาก การนำเสนอผลงาน

หนึ่งในรายงานจำนวนมากในการประชุมครั้งนี้ที่ทุ่มเทให้กับนวัตกรรมใน C++20 นั้นเป็นที่น่าจดจำไม่เพียงแต่สำหรับการนำเสนอที่มีสีสันเท่านั้น แต่ยังรวมถึงการระบุปัญหาที่มีอยู่อย่างชัดเจนด้วยตรรกะการประมวลผลคอลเลกชัน (สำหรับการวนซ้ำ การเรียกกลับ)

Adi Shavit เน้นย้ำสิ่งต่อไปนี้: วิธีการที่มีอยู่ในปัจจุบันจะผ่านคอลเลกชันทั้งหมดและไม่ได้ให้การเข้าถึงสถานะตัวกลางภายในบางอย่าง (หรือทำในกรณีของการโทรกลับ แต่มีผลข้างเคียงที่ไม่พึงประสงค์จำนวนมาก เช่น Callback Hell) . ดูเหมือนว่าจะมีตัววนซ้ำ แต่ถึงแม้จะมีพวกมันทุกอย่างก็ไม่ราบรื่นนัก: ไม่มีจุดเข้าและออกทั่วไป (เริ่มต้น → สิ้นสุด กับ rbegin → ฉีก และอื่นๆ) ยังไม่ชัดเจนว่าเราจะวนซ้ำนานแค่ไหน เริ่มต้นด้วย C++20 ปัญหาเหล่านี้ได้รับการแก้ไขแล้ว!

ตัวเลือกแรก: ช่วง ด้วยการรวมตัววนซ้ำ เราจะได้อินเทอร์เฟซทั่วไปสำหรับจุดเริ่มต้นและจุดสิ้นสุดของการวนซ้ำ และเรายังได้รับความสามารถในการเขียนอีกด้วย ทั้งหมดนี้ทำให้ง่ายต่อการสร้างไปป์ไลน์การประมวลผลข้อมูลเต็มรูปแบบ แต่ไม่ใช่ทุกอย่างจะราบรื่นนัก: ส่วนหนึ่งของตรรกะการคำนวณอยู่ภายในการใช้งานตัววนซ้ำเฉพาะ ซึ่งอาจทำให้โค้ดซับซ้อนในการทำความเข้าใจและแก้ไขข้อบกพร่อง

C++ รัสเซีย: มันเกิดขึ้นได้อย่างไร
เลื่อนจาก การนำเสนอผลงาน

สำหรับกรณีนี้ C++20 ได้เพิ่ม coroutines (ฟังก์ชันที่มีพฤติกรรมคล้ายกับตัวสร้างใน Python): การดำเนินการสามารถเลื่อนออกไปได้โดยการส่งคืนค่าปัจจุบันบางส่วนในขณะที่ยังคงรักษาสถานะระดับกลางเอาไว้ ดังนั้นเราจึงประสบความสำเร็จไม่เพียงแต่ทำงานกับข้อมูลตามที่ปรากฏเท่านั้น แต่ยังห่อหุ้มตรรกะทั้งหมดไว้ในโครูทีนเฉพาะอีกด้วย

แต่มีแมลงวันอยู่ในครีม: ในขณะนี้ คอมไพเลอร์ที่มีอยู่ได้รับการสนับสนุนเพียงบางส่วนเท่านั้นและยังไม่ได้นำไปใช้อย่างประณีตอย่างที่เราต้องการ: ตัวอย่างเช่นยังไม่คุ้มที่จะใช้การอ้างอิงและวัตถุชั่วคราวในโครูทีน นอกจากนี้ยังมีข้อจำกัดบางประการเกี่ยวกับสิ่งที่สามารถเป็น coroutines และฟังก์ชัน constexpr ตัวสร้าง/ตัวทำลาย และตัวหลักจะไม่รวมอยู่ในรายการนี้

ดังนั้น Coroutines จึงแก้ปัญหาส่วนสำคัญของปัญหาด้วยความเรียบง่ายของตรรกะการประมวลผลข้อมูล แต่การใช้งานในปัจจุบันจำเป็นต้องได้รับการปรับปรุง

วัสดุ:

เทคนิค C++ จาก Yandex.Taxi, Anton Polukhin

ในกิจกรรมระดับมืออาชีพของฉัน บางครั้งฉันต้องใช้สิ่งที่ช่วยเพียงอย่างเดียว: wrapper ระหว่างอินเทอร์เฟซภายในและ API ของไลบรารีบางตัว การบันทึกหรือการแยกวิเคราะห์ ในกรณีนี้ โดยปกติไม่จำเป็นต้องมีการเพิ่มประสิทธิภาพเพิ่มเติมใดๆ แต่จะเกิดอะไรขึ้นถ้าส่วนประกอบเหล่านี้ถูกใช้ในบริการยอดนิยมบางส่วนบน RuNet? ในสถานการณ์เช่นนี้ คุณจะต้องประมวลผลบันทึกเทราไบต์ต่อชั่วโมงเพียงอย่างเดียว! จากนั้นทุกมิลลิวินาทีก็มีค่าดังนั้นคุณต้องหันไปใช้กลอุบายต่าง ๆ - Anton Polukhin พูดถึงพวกเขา

บางทีตัวอย่างที่น่าสนใจที่สุดคือการนำรูปแบบ 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_; 
};

ในตัวอย่างนี้ ขั้นแรกฉันต้องการกำจัดไฟล์ส่วนหัวของไลบรารีภายนอก ซึ่งจะคอมไพล์เร็วขึ้น และคุณสามารถป้องกันตัวเองจากความขัดแย้งของชื่อที่เป็นไปได้และข้อผิดพลาดอื่น ๆ ที่คล้ายกัน 

โอเค เราย้าย #include ไปยังไฟล์ .cpp: เราจำเป็นต้องมีการประกาศส่งต่อของ API ที่ห่อไว้ เช่นเดียวกับ std::unique_ptr ขณะนี้ เรามีการจัดสรรแบบไดนามิกและสิ่งที่ไม่พึงประสงค์อื่นๆ เช่น ข้อมูลที่กระจัดกระจายไปตามกลุ่มข้อมูลและการรับประกันที่ลดลง 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<kImplSize, kImplAlign> data_; 
};

ปัญหาเดียว: เราจำเป็นต้องระบุขนาดและการจัดตำแหน่งสำหรับกระดาษห่อแต่ละอัน - มาสร้างเทมเพลต pimpl ของเราด้วยพารามิเตอร์ ใช้ค่าที่กำหนดเองและเพิ่มเช็คให้กับ destructor ว่าเราเดาทุกอย่างถูกต้องแล้ว : : 

~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 ถูกกำหนดไว้แล้วเมื่อประมวลผล destructor รหัสนี้จะถูกแยกวิเคราะห์อย่างถูกต้องและในขั้นตอนการคอมไพล์มันจะส่งออกขนาดและค่าการจัดตำแหน่งที่ต้องการซึ่งจำเป็นต้องป้อนเป็นข้อผิดพลาด ดังนั้น ด้วยค่าใช้จ่ายในการคอมไพล์เพิ่มเติมหนึ่งครั้ง เราจะกำจัดการจัดสรรคลาสที่ห่อแบบไดนามิก ซ่อน API ในไฟล์ .cpp พร้อมกับการใช้งาน และยังได้รับการออกแบบที่เหมาะสำหรับการแคชโดยโปรเซสเซอร์มากกว่า

การบันทึกและการแยกวิเคราะห์ดูไม่น่าประทับใจนัก และดังนั้นจึงไม่มีการกล่าวถึงในรีวิวนี้

สไลด์รายงานมีอยู่ที่ลิงค์ต่อไปนี้: ["เคล็ดลับ C++ จากแท็กซี่"]

เทคนิคสมัยใหม่ในการทำให้โค้ดของคุณแห้ง Björn Fahller

ในการบรรยายนี้ บียอร์น ฟาห์ลเลอร์แสดงวิธีต่างๆ หลายวิธีในการต่อสู้กับข้อบกพร่องด้านโวหารของการตรวจสอบสภาพซ้ำๆ:

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

ฟังดูคุ้นเคยใช่ไหม? ด้วยการใช้เทคนิค C++ อันทรงพลังหลายอย่างที่นำมาใช้ในมาตรฐานล่าสุด คุณสามารถใช้งานฟังก์ชันเดียวกันได้อย่างสวยงามโดยไม่มีการลดทอนประสิทธิภาพการทำงานใดๆ เปรียบเทียบ:   

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

ในการจัดการกับจำนวนเช็คที่ไม่คงที่ คุณจะต้องใช้เทมเพลตแปรผันและนิพจน์การพับทันที สมมติว่าเราต้องการตรวจสอบความเท่าเทียมกันของตัวแปรหลายตัวกับองค์ประกอบ state_type ของ enum สิ่งแรกที่นึกถึงคือการเขียนฟังก์ชันตัวช่วย 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) || ...); 
}

ผลลัพธ์ระดับกลางนี้น่าผิดหวัง จนถึงขณะนี้โค้ดยังไม่สามารถอ่านได้มากขึ้น:

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

พารามิเตอร์เทมเพลตที่ไม่ใช่ประเภทจะช่วยปรับปรุงสถานการณ์ได้เล็กน้อย ด้วยความช่วยเหลือของพวกเขา เราจะโอนองค์ประกอบนับได้ของแจงนับไปยังรายการพารามิเตอร์เทมเพลต: 

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

ด้วยการใช้ auto ในพารามิเตอร์เทมเพลตที่ไม่ใช่ประเภท (C++17) วิธีการจะสรุปการเปรียบเทียบไม่เพียงแต่กับองค์ประกอบ state_type เท่านั้น แต่ยังรวมไปถึงประเภทดั้งเดิมที่สามารถใช้เป็นพารามิเตอร์เทมเพลตที่ไม่ใช่ประเภทได้:


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

ด้วยการปรับปรุงอย่างต่อเนื่องเหล่านี้ ทำให้ได้ไวยากรณ์ที่คล่องแคล่วที่ต้องการสำหรับการตรวจสอบ:


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

ในตัวอย่างนี้ คู่มือการหักเงินทำหน้าที่แนะนำพารามิเตอร์เทมเพลตโครงสร้างที่ต้องการให้กับคอมไพเลอร์ ซึ่งทราบประเภทของอาร์กิวเมนต์ของ Constructor 

เพิ่มเติม - น่าสนใจยิ่งขึ้น Bjorn สอนวิธีสรุปโค้ดผลลัพธ์สำหรับตัวดำเนินการเปรียบเทียบที่เกิน == จากนั้นจึงสอนสำหรับการดำเนินการตามอำเภอใจ ในระหว่างนี้ มีการอธิบายคุณลักษณะต่างๆ เช่นแอตทริบิวต์ no_unique_address (C++20) และพารามิเตอร์เทมเพลตในฟังก์ชัน lambda (C++20) โดยใช้ตัวอย่างการใช้งาน (ใช่ ตอนนี้ไวยากรณ์แลมบ์ดานั้นง่ายต่อการจดจำ - นี่คือวงเล็บสี่คู่ติดต่อกันทุกประเภท) วิธีแก้ปัญหาสุดท้ายโดยใช้ฟังก์ชันเป็นรายละเอียดคอนสตรัคเตอร์ทำให้จิตวิญญาณของฉันอบอุ่นจริงๆ ไม่ต้องพูดถึงนิพจน์ทูเพิลในประเพณีที่ดีที่สุดของแลมบ์ดา แคลคูลัส.

ในตอนท้ายอย่าลืมขัดเกลามัน:

  • โปรดจำไว้ว่าแลมบ์ดาเป็น constexpr ฟรี 
  • มาเพิ่มการส่งต่อที่สมบูรณ์แบบและดูไวยากรณ์ที่น่าเกลียดซึ่งสัมพันธ์กับแพ็กพารามิเตอร์ในการปิดแลมบ์ดา
  • เรามาเพิ่มโอกาสให้คอมไพเลอร์ในการเพิ่มประสิทธิภาพด้วย noยกเว้นแบบมีเงื่อนไข 
  • มาดูแลเอาต์พุตข้อผิดพลาดที่เข้าใจได้ง่ายขึ้นในเทมเพลตด้วยค่าส่งคืนแลมบ์ดาที่ชัดเจน สิ่งนี้จะบังคับให้คอมไพลเลอร์ทำการตรวจสอบเพิ่มเติมก่อนที่จะเรียกใช้ฟังก์ชันเทมเพลตจริง - ในขั้นตอนการตรวจสอบประเภท 

สำหรับรายละเอียด โปรดดูเอกสารการบรรยาย: 

ความประทับใจของเรา

การเข้าร่วม C++ Russia ครั้งแรกของเรานั้นน่าจดจำสำหรับความเข้มข้นของมัน ฉันรู้สึกว่า C++ Russia เป็นงานที่จริงใจ โดยที่เส้นแบ่งระหว่างการฝึกอบรมและการสื่อสารสดแทบจะมองไม่เห็น ทุกสิ่งทุกอย่างตั้งแต่อารมณ์ของวิทยากรไปจนถึงการแข่งขันจากพันธมิตรในงานล้วนเอื้อต่อการอภิปรายอย่างดุเดือด เนื้อหาของการประชุมประกอบด้วยรายงาน ครอบคลุมหัวข้อที่หลากหลาย รวมถึงนวัตกรรม C++ กรณีศึกษาของโครงการขนาดใหญ่ และการพิจารณาทางสถาปัตยกรรมเชิงอุดมการณ์ แต่มันไม่ยุติธรรมเลยที่จะเพิกเฉยต่อองค์ประกอบทางสังคมของงาน ซึ่งช่วยเอาชนะอุปสรรคทางภาษาที่ไม่เพียงเกี่ยวข้องกับ C++ เท่านั้น

เราขอขอบคุณผู้จัดงานสัมมนาสำหรับโอกาสในการเข้าร่วมกิจกรรมดังกล่าว!
คุณอาจเคยเห็นโพสต์ของผู้จัดงานเกี่ยวกับอดีต ปัจจุบัน และอนาคตของ C++ Russia ในบล็อก JUG Ru.

ขอขอบคุณที่อ่าน และเราหวังว่าการเล่าเหตุการณ์ต่างๆ ของเราจะเป็นประโยชน์!

ที่มา: will.com

เพิ่มความคิดเห็น