मैं संकलन चरण में कीड़े के एक निश्चित वर्ग को पकड़ने के लिए दृढ़ता से टाइप किए गए टाइफेड घोषित करने का एक तरीका सोचने की कोशिश कर रहा हूं। यह अक्सर ऐसा होता है कि मैं कई प्रकार के आईडी, या स्थिति या वेग के लिए एक सदिश टाइप करूँगा:
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
दुर्भाग्य से, मेरे द्वारा दृढ़ता से टाइप किए गए टाइपफेड के लिए मिले सुझावों में बूस्ट का उपयोग करना शामिल है, जो कम से कम मेरे लिए एक संभावना नहीं है (मेरे पास सी ++ 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;
प्रकार अब पूरी तरह से अलग हैं। यदि आप उन्हें एक ModelID खिलाने की कोशिश करते हैं, तो EntityID लेने वाले कार्य एक संकलक त्रुटि को फेंक देंगे, उदाहरण के लिए। आधार के प्रकार को टेम्प्लेट के रूप में घोषित करने के अलावा, जो मुद्दे उलझते हैं, वह भी काफी कॉम्पैक्ट है।
मैं उम्मीद कर रहा था कि किसी को भी इस विचार के बारे में टिप्पणी या आलोचना करना चाहिए था?
उदाहरण के लिए पदों और वेगों के मामले में यह लिखते समय एक मुद्दा जो दिमाग में आया, वह यह होगा कि मैं पहले की तरह स्वतंत्र रूप से टाइप के बीच रूपांतरण नहीं कर सकता। जहां एक स्केलर द्वारा एक वेक्टर को गुणा करने से पहले एक और वेक्टर दिया जाएगा, इसलिए मैं कर सकता था:
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;
अपने दृढ़ता से टाइप किए गए टाइपफ़ीड के साथ, मुझे संकलक को बताना होगा कि किसी स्थिति में समय के परिणाम से वेग को गुणा करना।
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
इसे हल करने के लिए, मुझे लगता है कि मुझे हर रूपांतरण को स्पष्ट रूप से करना होगा, जो एक तरह का परेशान कर सकता है। दूसरी ओर, यह सीमा अन्य प्रकार की त्रुटियों को रोकने में मदद कर सकती है (जैसे, एक दूरी से वेग को गुणा करना, शायद, जो इस डोमेन में कोई मतलब नहीं होगा)। इसलिए मैं फटा हुआ हूं, और सोच रहा हूं कि क्या लोगों को मेरे मूल मुद्दे पर कोई राय है, या इसे हल करने के लिए मेरा दृष्टिकोण।