ฉันพยายามคิดวิธีประกาศ typedefs พิมพ์อย่างยิ่งเพื่อจับระดับหนึ่งของข้อบกพร่องในขั้นตอนการรวบรวม มันมักจะเป็นกรณีที่ฉันจะพิมพ์ int ลงในรหัสหลายประเภทหรือเวกเตอร์ไปยังตำแหน่งหรือความเร็ว:
typedef int EntityID;
typedef int ModelID;
typedef Vector3 Position;
typedef Vector3 Velocity;
สิ่งนี้สามารถทำให้เจตนาของรหัสชัดเจนยิ่งขึ้น แต่หลังจากการเขียนโค้ดคืนหนึ่งอาจทำให้เกิดข้อผิดพลาดที่โง่เขลาเช่นการเปรียบเทียบรหัสต่าง ๆ หรือเพิ่มตำแหน่งให้กับความเร็ว
EntityID eID;
ModelID mID;
if ( eID == mID ) // <- Compiler sees nothing wrong
{ /*bug*/ }
Position p;
Velocity v;
Position newP = p + v; // bug, meant p + v*s but compiler sees nothing wrong
น่าเสียดายที่คำแนะนำที่ฉันพบสำหรับ typedefs ที่พิมพ์อย่างมากรวมถึงการใช้ boost ซึ่งอย่างน้อยสำหรับฉันก็เป็นไปไม่ได้ (ฉันมี c ++ 11 อย่างน้อย) ดังนั้นหลังจากความคิดเล็กน้อยฉันก็มาถึงความคิดนี้และต้องการที่จะดำเนินการโดยใครบางคน
ก่อนอื่นคุณต้องประกาศประเภทฐานเป็นแม่แบบ พารามิเตอร์เทมเพลตไม่ได้ใช้สำหรับสิ่งใด ๆ ในนิยามอย่างไรก็ตาม:
template < typename T >
class IDType
{
unsigned int m_id;
public:
IDType( unsigned int const& i_id ): m_id {i_id} {};
friend bool operator==<T>( IDType<T> const& i_lhs, IDType<T> const& i_rhs );
};
ฟังก์ชั่นเพื่อนจะต้องมีการประกาศไปข้างหน้าก่อนการกำหนดคลาสซึ่งต้องมีการประกาศล่วงหน้าของเทมเพลตคลาส
จากนั้นเราจะกำหนดสมาชิกทั้งหมดสำหรับประเภทฐานเพียงแค่จำได้ว่ามันเป็นคลาสแม่แบบ
ในที่สุดเมื่อเราต้องการใช้งานเราพิมพ์มันเป็น:
class EntityT;
typedef IDType<EntityT> EntityID;
class ModelT;
typedef IDType<ModelT> ModelID;
ประเภทนี้แยกจากกันโดยสิ้นเชิง ฟังก์ชั่นที่ใช้ EntityID จะทำให้เกิดข้อผิดพลาดของคอมไพเลอร์หากคุณพยายามที่จะป้อน ModelID ให้พวกเขาแทน นอกเหนือจากการประกาศประเภทพื้นฐานเป็นแม่แบบด้วยปัญหาที่เกี่ยวข้องก็ยังมีขนาดกะทัดรัด
ฉันหวังว่าทุกคนจะมีความคิดเห็นหรือวิจารณ์เกี่ยวกับความคิดนี้
ประเด็นหนึ่งที่นึกขึ้นมาได้ในขณะที่เขียนสิ่งนี้ในกรณีของตำแหน่งและความเร็วเช่นว่าฉันจะไม่สามารถแปลงระหว่างประเภทต่าง ๆ ได้อย่างอิสระเหมือนเมื่อก่อน ที่ไหนก่อนที่จะคูณเวกเตอร์ด้วยสเกลาร์จะให้เวกเตอร์อีกอัน, ดังนั้นฉันทำได้:
typedef float Time;
typedef Vector3 Position;
typedef Vector3 Velocity;
Time t = 1.0f;
Position p = { 0.0f };
Velocity v = { 1.0f, 0.0f, 0.0f };
Position newP = p + v*t;
ด้วย typedef ที่พิมพ์ออกมาอย่างแรงของฉันฉันต้องบอกคอมไพเลอร์ว่าการคูณความเร็วด้วยเวลาทำให้ผลลัพธ์อยู่ในตำแหน่ง
class TimeT;
typedef Float<TimeT> Time;
class PositionT;
typedef Vector3<PositionT> Position;
class VelocityT;
typedef Vector3<VelocityT> Velocity;
Time t = 1.0f;
Position p = { 0.0f };
Velocity v = { 1.0f, 0.0f, 0.0f };
Position newP = p + v*t; // Compiler error
ในการแก้ปัญหานี้ฉันคิดว่าฉันต้องชำนาญทุกการแปลงอย่างชัดเจนซึ่งอาจเป็นเรื่องที่น่ารำคาญ ในทางกลับกันข้อ จำกัด นี้สามารถช่วยป้องกันข้อผิดพลาดประเภทอื่น ๆ (เช่นการคูณความเร็วด้วยระยะทางบางทีอาจไม่สมเหตุสมผลในโดเมนนี้) ดังนั้นฉันจึงถูกฉีกขาดและสงสัยว่าผู้คนมีความคิดเห็นใด ๆ เกี่ยวกับปัญหาดั้งเดิมของฉันหรือวิธีการของฉันในการแก้ไข