- โปรเจกต์ Chromium กำหนดขอบเขตการใช้งานและรายการต้องห้ามของฟีเจอร์มาตรฐาน C++ สมัยใหม่ไว้อย่างชัดเจน เพื่อรักษาความสม่ำเสมอของโค้ดและความปลอดภัย
- ตั้งแต่ C++11 ถึง C++23 จะมีการแยกสถานะของแต่ละมาตรฐานเป็น อนุญาต, ห้ามใช้ และอยู่ระหว่างพิจารณา (TBD) โดย ไลบรารี Abseil ก็ใช้เกณฑ์เดียวกัน
- ฟีเจอร์ที่ถูกห้ามใช้มีทั้ง std::shared_ptr, std::function, std::regex, std::filesystem, std::byte, char8_t, modules เป็นต้น
- ฟีเจอร์ที่อนุญาตให้ใช้ได้ เช่น concepts, ตัวดำเนินการ spaceship, designated initializer, std::to_underlying, อัลกอริทึม std::ranges
- คู่มือนี้ใช้กับ Chromium และทุกโปรเจกต์ย่อย โดยทำหน้าที่เป็นเกณฑ์สำคัญเพื่อให้ได้มาซึ่งเสถียรภาพของโค้ดและความเข้ากันได้ของการบิลด์
นโยบายการใช้ Modern C++ ของ Chromium
- Chromium ไม่ได้นำมาตรฐาน C++ ใหม่ล่าสุดมาใช้ทันที แต่จะกำหนดสถานะเป็น รองรับเบื้องต้น (initially supported) หลังจากที่ การรองรับของ toolchain มีความพร้อมเพียงพอ
- จากนั้นจึงแยกตามฟีเจอร์เป็นสถานะ อนุญาต (allowed), ห้ามใช้ (banned) และ อยู่ระหว่างพิจารณา (TBD)
- สามารถเสนอการเปลี่ยนสถานะของฟีเจอร์ใหม่ ๆ ได้ผ่าน เมลลิงลิสต์ cxx@chromium.org
- เมื่อผ่านไป 2 ปีหลังรองรับเบื้องต้น ฟีเจอร์จะถูกย้ายไปยังรายการอนุญาตหรือห้ามใช้ผ่านการพิจารณาอย่างชัดเจน
ฟีเจอร์ต้องห้ามใน C++11
- ฟีเจอร์ของภาษา: inline namespace, long long, user-defined literals
- ฟีเจอร์ของไลบรารี:
<chrono>, <regex>, <random> engine, <exception>, <ratio>, <thread> เป็นต้น
- exception ถูกปิดใช้งานทั้งหมด และอนุญาตเฉพาะ
noexcept
- ใช้ base::Bind, base::Callback, base::RefCounted แทน
std::bind, std::function, std::shared_ptr, std::weak_ptr
ฟีเจอร์ต้องห้ามใน C++17
- ห้ามใช้ UTF-8 character literal (u8) เนื่องจากมีปัญหาความเข้ากันได้กับ
char8_t
- รายการไลบรารีที่ห้ามใช้:
- ฟังก์ชันคณิตศาสตร์พิเศษ, parallel algorithms,
std::any, std::byte, std::filesystem, ทรัพยากรหน่วยความจำ std::pmr เป็นต้น
- parallel algorithms ถูกห้ามใช้เพราะ libc++ ยังไม่รองรับ และมีความกังวลว่าจะขัดกับโมเดลการทำงานแบบเธรดของ Chrome
ฟีเจอร์ที่อนุญาตและห้ามใช้ใน C++20
- ฟีเจอร์ของภาษาที่อนุญาต:
- concepts, consteval, designated initializers, ตัวดำเนินการ spaceship, [[likely]], ไวยากรณ์กำหนดค่าเริ่มต้นใน range-for
- ฟีเจอร์ของไลบรารีที่อนุญาต:
<bit>, <compare>, <concepts>, <numbers>, std::erase_if, std::ranges::subrange, std::to_underlying เป็นต้น
- ฟีเจอร์ที่ห้ามใช้:
- char8_t, modules, [[no_unique_address]],
std::bit_cast, <span>, std::bind_front, std::ranges::view_interface
- อยู่ระหว่างพิจารณา (TBD): coroutine,
<format>, <source_location>, std::u8string
ฟีเจอร์ที่อนุญาตและอยู่ระหว่างพิจารณาใน C++23
- ฟีเจอร์ของภาษาที่อนุญาต:
#elifdef, if consteval, static operator
- ฟีเจอร์ของไลบรารีที่อนุญาต:
std::byteswap, std::basic_string::contains, std::to_underlying, อัลกอริทึมขยายของ std::ranges
- ฟีเจอร์ที่อยู่ระหว่างพิจารณา:
std::expected, std::mdspan, std::generator, std::stacktrace, std::print, [[assume]], #warning เป็นต้น
นโยบายของไลบรารี Abseil
- องค์ประกอบของ Abseil ที่ห้ามใช้:
absl::any, absl::optional, absl::StatusOr, absl::Span, absl::FunctionRef, absl::Mutex, absl::Time, absl::btree_* เป็นต้น
- ส่วนใหญ่ถูกแทนที่ด้วย implementation ใน namespace base ของ Chromium (
base::span, base::expected, base::Bind เป็นต้น)
- อยู่ระหว่างพิจารณา (TBD):
absl::linked_hash_set, absl::linked_hash_map
ความหมายโดยรวม
- Chromium ไม่ได้รับฟีเจอร์มาตรฐาน C++ ทั้งหมดโดยอัตโนมัติ แต่เลือกใช้ตามเกณฑ์ด้านเสถียรภาพของการบิลด์ ความปลอดภัย ประสิทธิภาพ และความสม่ำเสมอของโค้ด
- ฟีเจอร์ที่ถูกห้ามใช้จำนวนมากมีสาเหตุจาก มีการทำซ้ำไว้แล้ว (base::) หรือ ปัญหาความเข้ากันได้ของ toolchain และ ABI
- คู่มือนี้ทำหน้าที่เป็น เอกสารเกณฑ์ควบคุมคุณภาพโค้ด C++ ของระบบนิเวศ Chromium และเป็นเอกสารอ้างอิงสำคัญในการทำงานร่วมกันแบบโอเพนซอร์ส
3 ความคิดเห็น
น่าเสียดายที่ C++ ยังคงพองตัวขึ้นเรื่อย ๆ เพื่อรักษาความเข้ากันได้แบบย้อนหลังของภาษา..
มันเป็นภาษาที่ใหญ่มหึมาจริง ๆ อย่างที่มีคนแสดงความเห็นใน HN ว่าไว้ C++ ...
ความคิดเห็นจาก Hacker News
ไม่มีอะไรสะดุดตาเป็นพิเศษ แต่ส่วนใหญ่ก็เป็นแนว "มาใช้ ไลบรารีที่ทำขึ้นใช้ภายในองค์กร ให้เหมาะกับงานของเรา"
ที่เหลือก็มีเหตุผลดี เช่น การหลีกเลี่ยงปัญหา locale และยังมีตัวเลือกที่ช่วยขัดเกลาส่วนหยาบ ๆ ของ standard library เลยพอเข้าใจได้
chronoเลยต้องทำ time type ขึ้นมาเอง และก็ใช้คอนเทนเนอร์ของตัวเองมาตั้งแต่ก่อน STL จะนิ่งถ้าจะเริ่มโปรเจ็กต์ใหม่ตอนนี้ กฎพวกนี้ส่วนใหญ่น่าจะไม่มีความหมายแล้ว
char8_tน่าสนใจดี ทุกวันนี้แทบไม่มี encoding อื่นที่ไม่ใช่ UTF-8 แล้ว และchar8_t*ก็เข้ากันกับchar*ไม่ได้ จึงแนะนำให้ใช้std::stringหรือstd::string_viewเพื่อหลีกเลี่ยง การ cast กันพร่ำเพรื่อพอพูดถึงโค้ดเก่าก็นึกถึงตอน Chromium ออกมาใหม่ ๆ
น่าทึ่งเหมือนกันที่โค้ดเบสนี้เริ่มต้นมาตั้งแต่ 20 ปีก่อน แล้ว
การแบน
<regex>เป็นการตัดสินใจที่ดี เพราะมันจัดการ UTF-8 ได้ไม่ถูกต้องจนใช้งานแทบไม่ได้ น่าแปลกที่ การออกแบบที่มีข้อบกพร่อง แบบนี้กลับถูกทำให้เป็นมาตรฐานยังมีเอกสารที่น่าสนใจกว่านี้อยู่ในไดเรกทอรีระดับบน
Chromium C++ Style Guide ก็น่าอ่าน
Exception ถูกแบน แต่ ยกเว้นบน Windows
ไม่ใช่ว่าคัดค้าน exception ในเชิงปรัชญา แต่แบนเพราะ เหตุผลเชิงปฏิบัติ ถ้าเริ่มจากศูนย์ใหม่คงตัดสินใจอีกแบบ
[[no_unique_address]]เลยนึกว่าคงพลาดมุกอะไรไปรายการฟีเจอร์ที่โดนแบนเยอะมาก จนดูเหมือนจะเยอะกว่าฟีเจอร์ทั้งหมดของ C เสียอีก ล้นหลามมาก
การแบนลิเทอรัล
u8"..."ถือว่าตัดสินใจดี ถ้าเขียนซอร์สเป็น UTF-8 อยู่แล้วก็ไม่จำเป็นต้องมี prefix แยกต่างหากลิเทอรัลแบบนี้เหมือน มีคำตอบก่อนจะมีปัญหา
อยากรู้ว่ามีอะไรใช้แทนฟีเจอร์ที่โดนแบนบ้าง เช่น
<filesystem>ที่บอกว่ารองรับการทดสอบไม่พอและมีช่องโหว่ด้านความปลอดภัย<filesystem>ที่เป็นข้อยกเว้นbase/filesModules ก็ถูกแบนเหมือนกัน ถ้าอย่างนั้นน่าจะก็อประบบโมดูลของ ภาษา D มาใช้เสียเลย
รายการของที่แบนแสดงให้เห็นว่า “บริบทสำคัญกว่า ฟีเจอร์ใหม่” แอปเล็ก ๆ อาจไม่มีปัญหา แต่ในโปรเจ็กต์ใหญ่เสี่ยงมาก
และยังคำนึงถึง ความสามารถในการพกพาข้ามแพลตฟอร์ม ด้วย