সংকলন পর্যায়ে একটি নির্দিষ্ট শ্রেণীর বাগগুলি ধরার জন্য আমি দৃ strongly়ভাবে টাইপড টাইপডেফগুলি ঘোষণা করার একটি উপায় সম্পর্কে ভাবতে চেষ্টা করেছি। এটি প্রায়শই এমন হয় যে আমি বিভিন্ন ধরণের আইডিতে একটি টাইপ করব, বা কোনও ভেক্টরকে অবস্থান বা বেগ দেবো:
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
দুর্ভাগ্যক্রমে, আমি দৃ strongly়ভাবে টাইপড টাইফিডগুলির জন্য পরামর্শগুলি পেয়েছি বুস্ট ব্যবহার করা অন্তর্ভুক্ত যা কমপক্ষে আমার পক্ষে কোনও সম্ভাবনা নয় (আমার কমপক্ষে সি ++ 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
শেষ অবধি, যখন আমরা এটি ব্যবহার করতে চাই, আমরা এটিকে টাইপ করি:
class EntityT;
typedef IDType<EntityT> EntityID;
class ModelT;
typedef IDType<ModelT> 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;
আমার দৃ strongly়ভাবে টাইপডেফের সাথে আমাকে সংকলকটি বলতে হবে যে সময় দ্বারা একটি বেগকে মাল্টিপলিং করার ফলে একটি অবস্থানের ফলাফল হয়।
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
এটি সমাধান করার জন্য, আমি মনে করি আমাকে প্রতিটি রূপান্তরকে স্পষ্টভাবে বিশেষীকরণ করতে হবে, যা এক ধরনের বিরক্তিকর হতে পারে। অন্যদিকে, এই সীমাবদ্ধতা অন্যান্য ধরণের ত্রুটিগুলি রোধ করতে সহায়তা করে (বলুন, একটি দূরত্বের দ্বারা একটি বেগকে গুণ করা যায়, সম্ভবত, যা এই ডোমেনটির কোনও অর্থ হবে না)। সুতরাং আমি ছিঁড়ে যাচ্ছি, এবং ভাবছি লোকেরা কি আমার মূল ইস্যুতে, বা এটি সমাধান করার বিষয়ে আমার মতামত নিয়ে কোনও মতামত রয়েছে।