الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

التحويلات داخل الـ template

بدأه C++er في 11 أغسطس 2011 · 2 رد · 587 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

لدي النوعين int_t و uint_t و محتواهم كالتالي:

template <typename lo_t> struct uint_t;

template <typename hi_t, typename lo_t>
struct int_t
{
	lo_t lo;
	hi_t hi;

	int_t() : hi(0), lo(0) {}
	int_t(int value) : lo(value), hi(value<0? -1: 0) {}
	int_t(unsigned value) : lo(value), hi(0) {}

	int_t(const uint_t<lo_t>&);

	//template<typename ty_a, typename ty_b>
	//int_t(const int_t<ty_a, ty_b>&);
};

template <typename hi_lo>
struct uint_t
{
	hi_lo lo, hi;

	uint_t() : lo(0), hi(0) {}
	uint_t(int value) : lo(value), hi(value<0? -1: 0) {}
	uint_t(unsigned value) : lo(value), hi(0) {}

	template<typename hi_t>
	uint_t(const int_t<hi_t, hi_lo>&);

	//template<typename ty>
	//uint_t(const uint_t<ty>&);
};

template <typename hi_t, typename lo_t>
int_t<hi_t, lo_t>::int_t(const uint_t<lo_t>& value) : hi(value.hi), lo(value.lo)
{}

template <typename hi_lo>
template <typename hi_t>
uint_t<hi_lo>::uint_t(const int_t<hi_t, hi_lo>& value) : hi(value.hi), lo(value.lo)
{}

الفئتان int_t و uint_t تمثلان النوعين signed int و unsigned int لأنواع ذات مساحات اكبر مما تتعامل معها اللغه، و كما نعلم ان النوع int الجزء الأعلي منه يكون signed و ذلك لأنه يحتوى على الـ sign bit كذلك النوع int_t يحتاج لأن يكون الـ hi_t بنفس حجم الـ lo_t و لكن الـ hi_t يكون signed type و الـ lo_t يكون unsigned type.

لجعل الفئتين تتعاملا مع الأنواع الإفتراضيه قمت بوضع المشيدان اللذان يأخذا النوعين int و unsigned int، الأن كمثال على إستخدامهم:

typedef  int_t<int, unsigned>  int64;
typedef uint_t<unsigned>      uint64;

int64 a = 1000;
int64 b = -512;

uint64 x = 1000;
uint64 y = -512;

العقبه الأولي هى امكانية التحويل بين نوعين لهما يأخذا نفس المساحه و لكن الـ hi_t لأحدهما signed و الاخر unsigned و لتخطئ هذه العقبه قمت بكتابة المشيد الذى يأخذ نوع مخالف لنوعه:

template <typename lo_t> struct uint_t;

template <typename hi_t, typename lo_t>
struct int_t
{
	.
	.
	.

	int_t(const uint_t<lo_t>&);

	.
	.
	.
};

template <typename hi_lo>
struct uint_t
{
	.
	.
	.

	template<typename hi_t>
	uint_t(const int_t<hi_t, hi_lo>&);

	.
	.
	.
};

template <typename hi_t, typename lo_t>
int_t<hi_t, lo_t>::int_t(const uint_t<lo_t>& value) : hi(value.hi), lo(value.lo)
{}

template <typename hi_lo>
template <typename hi_t>
uint_t<hi_lo>::uint_t(const int_t<hi_t, hi_lo>& value) : hi(value.hi), lo(value.lo)
{}

بالكود السابق نستطيع بكل سهوله التحويل بين اى نوعين الـ lo_t لهما متماثل:

typedef  int_t<int, unsigned>  int64;
typedef uint_t<unsigned>      uint64;

int64  a = 1000;
uint64 b = a;

uint64 x = 512;
 int64 y = x;

العقبه الأخيره و هي محور هذا السؤال هى التحويل بين نوع و اخر اكبر او اقل منه:

typedef  int_t<int, unsigned>  int64;
typedef uint_t<unsigned>      uint64;

typedef  int_t<int64, uint64> int128;
typedef uint_t<uint64>       uint128;

 int64 a = 1024;
int128 b = a;

int128 x = 100;
 int64 y = x;

الكود السابق لن يتم ترجمته إلا لو قمت بحذف التعليق الموجود على المشيد بالفئه int_t، دعك من الفئه uint_t الأن حيث إذا تم كتابة كود المشيد التالي فيمكن بسهوله برمجة المشيد الخاص بالفئه uint_t

template<typename ty_a, typename ty_b>
int_t(const int_t<ty_a, ty_b>&)
{
}

السؤال: ما هو شكل الكود الذى سيتم كتابته فى هذا المشيد ليعمل المثال السابق؟ (الكود المطلوب لـ Little Endian و Big Endian)

و الله ولي التوفيق

تم تعديل هذه المشاركة بواسطة محمد علاء الدين في 11 أغسطس 2011 في 21:55

1

مدونتي: C++ Tips and Tricks

#2

الحمد لله انتهيت من الكود الخاص بالـ Little Endian :

template<typename ty_a, typename ty_b>
int_t(const int_t<ty_a, ty_b>& value)
{
    *this = value < 0? -1: 0;

    if (sizeof(*this) < sizeof(value))
        *this = *(int_t*)&value;
    else
        *(int_t<ty_a, ty_b>*)&lo = value;
}

يتبقي الكود الخاص بالـ Big Endian

تم تعديل هذه المشاركة بواسطة محمد علاء الدين في 11 أغسطس 2011 في 22:05

مدونتي: C++ Tips and Tricks

#3

الحمد لله انتهيت من الكود الخاص بالـ Big Endian :

template<typename ty_a, typename ty_b>
int_t(const int_t<ty_a, ty_b>& value)
{
    *this = value < 0? -1: 0;

    if (sizeof(*this) < sizeof(value))
        *this = *((int_t*)&value.lo + (sizeof(value.lo)/sizeof(*this) - 1));
    else
        *((int_t<ty_a, ty_b>*)&hi + sizeof(*this)/sizeof(value) - 1) = value;
}

بالتالي تم الحصول على الإجابات كلها و يصبح الشكل النهائي للمشيد:

template<typename ty_a, typename ty_b>
int_t(const int_t<ty_a, ty_b>& value)
{
    *this = value < 0? -1: 0;

#ifdef BIG_ENDIAN
    if (sizeof(*this) < sizeof(value))
        *this = *((int_t*)&value.lo + (sizeof(value.lo)/sizeof(*this) - 1));
    else
        *((int_t<ty_a, ty_b>*)&hi + sizeof(*this)/sizeof(value) - 1) = value;
#else
    if (sizeof(*this) < sizeof(value))
        *this = *(int_t*)&value;
    else
        *(int_t<ty_a, ty_b>*)&lo = value;
#endif
}

و الله ولي التوفيق

مدونتي: C++ Tips and Tricks

مواضيع مشابهة