ตอนที่ 24: โดย Łukasz Anforowicz ใน Bellevue, วอชิงตัน (สิงหาคม 2021)
ตอนก่อนหน้า
คุณหาข้อบกพร่องในโค้ดด้านล่างได้ไหม เธอจะเห็นไหม ข้อบกพร่อง ในการตรวจสอบโค้ด เมื่อดูแค่ในเว็บไซต์ Callsite
Token CreateToken(int command_data, int buffer_id);
...
auto token = CreateToken(GetCommandBufferId(), GetCommandData());
บางครั้งประเภทเดียวกันอาจแสดงค่าจากโดเมนที่ใช้ร่วมกันไม่ได้
ซึ่งมักเกิดขึ้นสำหรับข้อมูลประเภทที่ไม่เฉพาะเจาะจง เช่น จำนวนเต็มหรือสตริง
ตัวอย่างด้านบนแสดงให้เห็นว่าการดำเนินการนี้อาจทำให้ข้อบกพร่องเกิดขึ้นได้อย่างไร
โชคดีที่ //base
ของ Chromium ทำให้คุณแนะนำประเภทที่แตกต่างกันอย่างชัดเจนได้อย่างง่ายดาย ดังนี้
#include "base/types/strong_alias.h"
// The first template argument of StrongAlias is a "tag" type.
// The "tag" type is used to distinguish between different
// StrongAlias types.
using CommandData = base::StrongAlias<class CommandDataTag, int>;
using CommandBufferId = base::StrongAlias<class CommandBufferIdTag, int>;
Token CreateToken(CommandData command_data, CommandBufferId buffer_id);
การแยกประเภทจะช่วยให้อ่านง่ายขึ้น
นอกจากนี้ StrongAlias
จะตรวจจับประเภทมิกซ์ขณะคอมไพล์:
test.cc:456:16: error: no matching function for call to 'CreateToken'
auto token = CreateToken(GetCommandBufferId(), GetCommandData());
^~~~~~~~~~~
test.cc:123:7: note: candidate function not viable: no known conversion from
'StrongAlias<class CommandBufferIdTag, [...]>' to
'StrongAlias<class CommandDataTag, [...]>' for 1st argument
Token CreateToken(CommandData command_data, CommandBufferId buffer_id);
^
เมื่อคอมไพเลอร์จะเห็น
ประเภทที่ใช้ร่วมกันไม่ได้
เพราะมี "แท็ก" ที่ต่างกัน ประเภท
StrongAlias
ยอมรับประเภทใดก็ได้เป็น "แท็ก" ประเภท
ตัวอย่างนี้แสดงให้เห็นว่า "แท็ก" ไม่จำเป็นต้องกำหนดประเภทด้วยซ้ำในทุกที่
การประกาศล่วงหน้าว่าไม่มีคลาสที่มีอยู่จริงนั้นใช้ได้ดี
ในอนาคต แทนที่จะเป็นประเภทที่ไม่เจาะจง (เช่น bool, int, สตริง) โปรดพิจารณาทางเลือกต่อไปนี้
- ใช้
base::IdType32<TagType>
แทนการใช้int32_t
เป็นตัวระบุ - ใช้
base::TokenType<TagType>
แทนbase::UnguessableToken
ที่ไม่เฉพาะเจาะจง - ใช้คลาส enum แทนบูลีน
(เช่น
kForReload
,kNotForReload
แทนที่จะเป็นtrue
,false
) - แทนที่ประเภทอื่นๆ ที่ไม่เฉพาะเจาะจงด้วย
base::StrongAlias<TagType, SomeWrappedType>