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

الحب من النظرة 13 ... Meta Programming

بدأه مصطفى 36a2 في 12 نوفمبر 2013 · 36 رد · 2,215 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#26

بالنسبة للـIF فقد تعمدت وضعها حتى يظهر Compile error عندما لا يتحقق الشرط

على كل حال هذا هو الكود المطلوب ولكنه لا يحقق المجال المطلوب .. (وحصلت على all test passed)

#include <iostream>
#include <climits>
using std::cout;
using std::endl;

typedef unsigned long long int ulli;

template <typename x>struct getMax{static const ulli max = 0;};

template <>struct getMax<unsigned char            >{static const ulli max = UCHAR_MAX    ;};
template <>struct getMax<signed char            >{static const ulli max = CHAR_MAX    ;};
template <>struct getMax<unsigned short int        >{static const ulli max = USHRT_MAX    ;};
template <>struct getMax<signed short int        >{static const ulli max = SHRT_MAX    ;};
template <>struct getMax<unsigned int            >{static const ulli max = UINT_MAX    ;};
template <>struct getMax<signed int            >{static const ulli max = INT_MAX    ;};
template <>struct getMax<unsigned long long int    >{static const ulli max = ULLONG_MAX;};
template <>struct getMax<signed long long int    >{static const ulli max = LLONG_MAX;};

template<ulli base  ,ulli num >
    struct counter
    {
        static const ulli value = (counter<base,num/base>::value)+bool(num);
    };
template<ulli base>
    struct counter<base,0>
    {
        static const ulli value = 0;
    };

template <    typename tName    ,    ulli base = 10 >
    struct digits_in_base_for_type
    {
        static const ulli value =
            (base<2||((base-1)<=getMax<tName>::max))?counter < base , getMax<tName>::max    >::value    : 0;
    };

فكيف أمنع المستخدم من إضافة القيم الممنوعة ؟

#27
اقتباس
فكيف أمنع المستخدم من إضافة القيم الممنوعة ؟

بالتعديل التالي:

template<typename tName, ulli base = 10, bool is_valid_range = base<2||((base-1)<=getMax<tName>::max)>
struct digits_in_base_for_type;

template<typename tName, ulli base>
struct digits_in_base_for_type<tName, base, true>
{
        static const ulli value = counter<base, getMax<tName>::max >::value;
};

و هذا هو حلي:

typedef   signed char  int8_t;
typedef unsigned char uint8_t;

typedef   signed short int  int16_t;
typedef unsigned short int uint16_t;

typedef   signed int  int32_t;
typedef unsigned int uint32_t;

typedef   signed long long int  int64_t;
typedef unsigned long long int uint64_t;

template<typename type> struct max { static const uint64_t value = (type)~0; };
template<> struct max<int8_t > { static const uint64_t value = max<uint8_t>::value >> 1; };
template<> struct max<int16_t> { static const uint64_t value = max<uint16_t>::value >> 1; };
template<> struct max<int32_t> { static const uint64_t value = max<uint32_t>::value >> 1; };
template<> struct max<int64_t> { static const uint64_t value = max<uint64_t>::value >> 1; };

template<uint64_t base, uint64_t input>
struct compute
{
	static const uint64_t value = 1 + compute< base, input/base >::value;
};
template<uint64_t base> struct compute<base, 0> { static const uint64_t value = 0; };

template<typename type, uint64_t base> struct check_base  { static const bool value = (base >= 2 && (base <= max<type>::value + 1)); };
template<uint64_t base> struct check_base<uint64_t, base> { static const bool value = (base >= 2 && base <= ~0ull); };

template<typename type, uint64_t base = 10, bool is_valid_range = check_base<type, base>::value >
struct digits_in_base_for_type;

template<typename type, uint64_t base>
struct digits_in_base_for_type<type, base, true>
{
	static const uint64_t value = compute<base, max<type>::value >::value;
};

السؤال التالي:

المفهوم cv-qualifier هو تعريف object بإستخدام const او volatile او const volatile. المطلوب هو ان يدخل نوع معين و تقوم انت بالتالي:

#define CREATE_DEF(name)  \
template<typename t> \
struct name \
{ \
    typedef /* implementation-defined */ type; \
};

#define CREATE_DEF2(name)  \
template<typename t> \
struct name \
{ \
    static const bool value = ?; \
};

CREATE_DEF(add_const)
CREATE_DEF(add_volatile)
CREATE_DEF(add_cv)

CREATE_DEF(remove_const)
CREATE_DEF(remove_volatile)
CREATE_DEF(remove_cv)

CREATE_DEF(is_const)
CREATE_DEF(is_volatile)
CREATE_DEF(is_cv)

حيث

add_const: تقوم بإضافة const فإن كان موجود فلا تاثير لها.

add_volatile: تقوم بإضافة volatile فإن كان موجود فلا تاثير لها.

add_cv: تقوم بإضافة const volatile فإن كانت موجود فلا تاثير لها.

 

remove_const: تقوم بحذف const فإن كان غير موجود فلا تاثير لها.

remove_volatile: تقوم بحذف volatile فإن كان غير موجود فلا تاثير لها.

remove_cv: تقوم بحذف const volatile فإن كانت غير موجود فلا تاثير لها.

 

is_const: تعيد true إذا كان النوع المدخل يحتوى على const.

is_volatile: تعيد true إذا كان النوع المدخل يحتوى على volatile.

is_cv: تعيد true إذا كان النوع المدخل يحتوى على const volatile.

 

الـ test case بعد قليل.

 

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

1

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

#28

كود الـ test case

#include <iostream>using std::cout;struct test_data{	bool user_res;	bool org_res;};const test_data data[] ={	{ is_const<int>::value, false },	{ is_const<const int>::value, true },	{ is_const<volatile int>::value, false },	{ is_const<const volatile int>::value, true },	{ is_volatile<int>::value, false },	{ is_volatile<const int>::value, false },	{ is_volatile<volatile int>::value, true },	{ is_volatile<const volatile int>::value, true },	{ is_cv<int>::value, false },	{ is_cv<const int>::value, false },	{ is_cv<volatile int>::value, false },	{ is_cv<const volatile int>::value, true },	{ is_const< add_const<int>::type >::value, true },	{ is_const< add_const<const int>::type >::value, true },	{ is_const< add_const<volatile int>::type >::value, true },	{ is_const< add_const<const volatile int>::type >::value, true },	{ is_volatile< add_volatile<int>::type >::value, true },	{ is_volatile< add_volatile<const int>::type >::value, true },	{ is_volatile< add_volatile<volatile int>::type >::value, true },	{ is_volatile< add_volatile<const volatile int>::type >::value, true },	{ is_cv< add_cv<int>::type >::value, true },	{ is_cv< add_cv<const int>::type >::value, true },	{ is_cv< add_cv<volatile int>::type >::value, true },	{ is_cv< add_cv<const volatile int>::type >::value, true },	{ is_const< remove_const<int>::type >::value, false },	{ is_const< remove_const<const int>::type >::value, false },	{ is_const< remove_const<volatile int>::type >::value, false },	{ is_const< remove_const<const volatile int>::type >::value, false },	{ is_volatile< remove_volatile<int>::type >::value, false },	{ is_volatile< remove_volatile<const int>::type >::value, false },	{ is_volatile< remove_volatile<volatile int>::type >::value, false },	{ is_volatile< remove_volatile<const volatile int>::type >::value, false },	{ is_cv< remove_cv<int>::type >::value, false },	{ is_cv< remove_cv<const int>::type >::value, false },	{ is_cv< remove_cv<volatile int>::type >::value, false },	{ is_cv< remove_cv<const volatile int>::type >::value, false }};static const int case_count = 36;int main(){	for(int i = 0; i < case_count; ++i)	{		if (data.user_res != data.org_res)		{			cout << "case " << i+1 << " failed.\n";			return 1;		}	}	cout << "all test passed.\n";}

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

تم تعديل هذه المشاركة بواسطة C++er في 15 نوفمبر 2013 في 19:46

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

#29

جزاك الله خيراً ... 

أعتذر للتأخر , بينما كنت أغلق الألسنة الكثيرة المفتوحة .. 

بالنسبة للتعديل :

template<typename tName, ulli base = 10, bool is_valid_range = base<2||((base-1)<=getMax<tName>::max)>

فهو لم (ولن) يعمل .. حسب الوثائق كما تعلم :) ... حيث قرأت أن استخدام إشارة > هي من أسوأ الكوابيس في templates .. أليس كذلك :D

 

بالنسبة لما قلته عن : أليس المفترض ألا يتم توليد الكود لأنه لم يتم استدعاء الدالة أبداً ..

ب 

فقد عدت إلى المكان الذي قرأتها منه .. (الإكسير صفحة 104 ) ويبدو أن الأخ الثبيتي كان مخطئاً .. أو أن إصدار اللغة في ذاك الوقت كان مختلفاً في هذه النقطة ..

بالنسبة لحلّك للمسألة 

ألا ترى أن هذا الكود لن يفيد ؟

template<uint64_t base> struct check_base<uint64_t, base> { static const bool value = (base >= 2 && base <= ~0ull); };

بالنسبة للفكرة :

template<typename type, uint64_t base = 10, bool is_valid_range = check_base<type, base>::value >
struct digits_in_base_for_type;

هل هناك أي طريقة أخرى ؟ لم أكن أتوقّع أن توليد الخطأ بهذه الصعوبة !

____________________

بالنسبة للسؤال الجديد .. سأبدأ التفكير به ..إذا كان فهمي التالي صحيحاً فلا تجبني : المطلوب تنفيذ جميع القوالب الواردة في الكود التالي

CREATE_DEF(add_const)
CREATE_DEF(add_volatile)
CREATE_DEF(add_cv)

CREATE_DEF(remove_const)
CREATE_DEF(remove_volatile)
CREATE_DEF(remove_cv)

CREATE_DEF(is_const)
CREATE_DEF(is_volatile)
CREATE_DEF(is_cv)

وهناك 9 من /* implementation-defined */  وليست واحدة فقط ..

 

وشكرا جزيلاً لك .

#30
اقتباس
فهو لم (ولن) يعمل .. حسب الوثائق كما تعلم :) ...

هو يعمل لدى جيدا على مترجم c++03 و c++11.

قائمة المترجمات التى استخدمها اسردتها من قبل.

 

اقتباس
حيث قرأت أن استخدام إشارة > هي من أسوأ الكوابيس في templates .. أليس كذلك :D

فقط عندما تكون قبل نهاية تعريف سطر الـ templates (أى تماثل shift-left-operator)، و هذا فى c++03 و ما قبلها فقط.

 

اقتباس
ألا ترى أن هذا الكود لن يفيد ؟

هذا الكود هام جدا لإنك إن لم تستخدمه و استخدمت الأخر سيحدث overflow عند إضافة 1 لأكبر قيمة يمكن تمثيلها داخل unsigned long long و لن يتم الترجمه.

فى هذه النقطة قمت أنت بإستخدام طريقة أوضح.

 

اقتباس
هل هناك أي طريقة أخرى ؟ لم أكن أتوقّع أن توليد الخطأ بهذه الصعوبة !

أولا: بالتأكيد توجد طرق أخرى و لكني لم افكر فيها.

ثانيا: هذه ليست طريقة لتوليد خطأ، هذا فقط عبارة عن incomplete-type و سيتم إستخدامه عندما تكون قيمة is_valid_range بـ false و فى هذه الحالة ستظهر رسالة خطأ تفيد بإستخدامك لـ incomplete-type.

 

اقتباس
.إذا كان فهمي التالي صحيحاً فلا تجبني

لن أجيب :)

 

 

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

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

#31

ستقول أنني مجنون :D ولكن هذا هو حلّي :

#define CREATE_DEF(name)  \
template<typename t> \
struct name \
{ \
    typedef typename t type; \
};
#define CREATE_DEF2(name)  \
template<typename t> \
struct name \
{ \
    static const bool value = false; \
};

CREATE_DEF(add_const)
CREATE_DEF(add_volatile)
CREATE_DEF(add_cv)

CREATE_DEF(remove_const)
CREATE_DEF(remove_volatile)
CREATE_DEF(remove_cv)

CREATE_DEF2(is_const)
CREATE_DEF2(is_volatile)
CREATE_DEF2(is_cv)

#define Helper3(H,x)            H(signed x)H(unsigned x)
#define Helper4(H,x,specifier)    H(specifier signed x)H(specifier unsigned x)
#define Helper(H,x,specifier)    Helper3(H,x)Helper4(H,x,specifier)
#define Helper2(H,x)            Helper3(H,x)Helper4(H,x,const)Helper4(H,x,volatile)

#define AC(x)  template<>struct add_const   <x>   {typedef const x type;};
#define AV(x)  template<>struct add_volatile<x>{typedef volatile x type;};
#define ACV(x) template<>struct add_cv<x>{typedef const volatile x type;};

#define RC(x)  template<>struct remove_const   <const x>   {typedef x type;};
#define RV(x)  template<>struct remove_volatile<volatile x>{typedef x type;};
#define RCV(x) template<>struct remove_cv<volatile const x>{typedef x type;};

#define IC(x)    template<>struct is_const    <const x>    {static const bool value = true;};
#define IV(x)    template<>struct is_volatile<volatile x>{static const bool value = true;};
#define ICV(x)    template<>struct is_cv<const volatile x>{static const bool value = true;};

#define XC(X,Y) X(char)X(Y char)Helper(X,char,Y)Helper(X,short,Y)Helper(X,int,Y)Helper(X,long long,Y)

XC(AC,volatile)XC(IC,volatile)XC(RC,volatile)

XC(AV,const)XC(IV,const)XC(RV,const)

ACV(char)ACV(const char)ACV(volatile char)Helper2(ACV,char)Helper2(ACV,short)Helper2(ACV,int)Helper2(ACV,long long)
ICV(char)Helper3(ICV,char)Helper3(ICV,short)Helper3(ICV,int)Helper3(ICV,long long)
RCV(char)Helper3(RCV,char)Helper3(RCV,short)Helper3(RCV,int)Helper3(RCV,long long)

:D

جزاك الله خيراً ...

لا أدري إن كنت قد ابتعدت كثيراً عن حلّك أم لا .. ولكن على العموم كانت تجربة مسلّية ..

( بصراحة لم أتوقّعه بهذه السهولة .. قضيت بعض الوقت في محاولة فهم volatile ولكن يبدو أنها مثل register وinline تعتمد على مزاج المصرّف )

#32

أولا انا دخت من قرائة الكود.

ثانيا إجابتك كانت صدمه.

ثالثا الأنواع اللى انا طلبتها منك هى جزء من مكتبة type_traits الموجوده بالـ c++11 standard و اللى قادمة اصلا من boost.

 

 

إقرا الكود المحتمل لكل منهم من هذا الرابط.

 

 

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

1

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

#33

سامحني هذا ما تعودت عليه عندما لا أعرف كيف أحل .. أن أرجع إلى الــtrivail solution وهنا قمت باختبار جميع الحالات ..

فكرة الكود هي كتابة  قالب معرف بشكل جزئي

مثل :

template<>struct is_const    <const x>    {static const bool value = true;};

حيث x يمكن أن يكون أي نوع int ,char إلخ ..

وحتى أقوم بذلك قمت باستعمال define الخارقة .. :p

ولأنيي وجدت كثيرأ من أجزاء الكود مكررة .. قمت بإدخال macro  بداخل macro  على 5 مراحل حتى صار الكود بهذا التعقيد ..

عندما تجد الرمز V فهو يعني أن الـmacro خاص بالتعامل مع volatile

C تعامل مع const  ..

ِA تعني Add

I اختصارا لــ is ? للاختبار

R أول حرف من remove

 

أما MACROS الــHelper فهي فقط لاختيار الأنواع المطلوب اختبارها ( وهي تقوم بتفريع كل نوع إلى signed و unsigned ) ومنها ما يقوم بالتفريع إلى volatile , const ..

وهكذا ..

 

في النهاية .. هل اشتغل الكود عندك ؟ :)

وهل الحل مقبول ؟ إجابتك كانت تعني لا :D

ماذا أفعل الآن ؟

#34

عرفت لماذان انصدمت :D

فال لا أحب التعقيد قال ...

template<typename t>struct add_const    {typedef typename const t type;};
template<typename t>struct add_volatile    {typedef typename volatile t type;};
template<typename t>struct add_cv        {typedef typename const volatile t type;};

template<typename t>struct is_const            {static const bool value = false;};
template<typename t>struct is_const<const t>{static const bool value = true;};

template<typename t>struct is_volatile                {static const bool value = false;};
template<typename t>struct is_volatile<volatile t>    {static const bool value = true;};

template<typename t>struct is_cv                    {static const bool value = false;};
template<typename t>struct is_cv<const volatile t>    {static const bool value = true;};

template<typename t>struct remove_const{typedef typename t type;};
template<typename t>struct remove_const<const t>{typedef typename t type;};

template<typename t>struct remove_volatile{typedef typename t type;};
template<typename t>struct remove_volatile<const t>{typedef typename t type;};

template<typename t>struct remove_cv{typedef typename t type;};
template<typename t>struct remove_cv<const t>{typedef typename t type;};

وسأعود بحل أقصر باستخدام define # بعد قليل بإذن الله

جزاك الله خيراً

#35

هذا هو الحل بعد التقصير رقم 1 .

#define Add(x,y) template<typename t>struct x    {typedef typename y t type;};

Add(add_const,const)
Add(add_volatile,volatile)
Add(add_cv,const volatile)

#define Is(x,y) template<typename t>struct x     {static const bool value = false;};\
                template<typename t>struct x<y t>{static const bool value = true;};
Is(is_const,const)
Is(is_volatile,volatile)
Is(is_cv,const volatile)

#define Remove(x,y) template<typename t>struct x{typedef typename t type;};\
                    template<typename t>struct x<y t>{typedef typename t type;};

Remove(remove_const,const)
Remove(remove_volatile,volatile)
Remove(remove_cv,const volatile)

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 18 نوفمبر 2013 في 00:35 — السبب: حال القصير!

#36

وهذه ضربتي الأخيرة :D

الحل القصير 2 ..

#define DO(x,y) Add(add_##x,y)Is(is_##x,y)Remove(remove_##x,y)
#define Add(x,y) template<typename t>struct x    {typedef typename y t type;};

#define Is(x,y) template<typename t>struct x     {static const bool value = false;};\
                template<typename t>struct x<y t>{static const bool value = true;};

#define Remove(x,y) template<typename t>struct x{typedef typename t type;};\
                    template<typename t>struct x<y t>{typedef typename t type;};

DO(const,const)
DO(volatile,volatile)
DO(cv,const volatile)

 

هل هناك سؤال آخر :) وأعدك أن أتوقف عن الحلول السخيفة :D

جزاك الله خيراً

#37

typename تستخدم لإعلام المترجم انك تشير إلى sub-type و ليس class member و هذه الحالة فقط تكون داخل template-class.

 

اقتباس
هل هناك سؤال آخر

بالتأكيد، أعطنى بعض الوقت.

 

 

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

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

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