दिलचस्प पोस्ट
जेएसएफ में संसाधनबंडल प्रविष्टियों के साथ अंतर्राष्ट्रीयकरण जो डेटाबेस से लोड किए जाते हैं उपयोगकर्ता के साथ कोनेर 2 गतिशील टैब चयनित घटक क्लिक करें AJAX डेटा के लिए json ऑब्जेक्ट या सरणी को जेसन में परिवर्तित करें कॉन्फ़िगर करना ताकि pip स्थापना github से काम कर सके तालिकाओं की सूची, और प्रत्येक में फ़ील्ड, डेटाबेस में प्राप्त करना खुलने / बंद टैग और प्रदर्शन? डॉट सिंटैक्स और स्क्वायर ब्रैकेट सिंटैक्स के बीच अंतर क्या है? इनपुट पाठ तत्व पर सीमा को उजागर कैसे करें आप जावा में दिनांक कैसे घटाना चाहते हैं? एक्स लगातार दिनों के लिए जांचें – डेटाबेस में दिए गए टाइमस्टैंप मैं अपने मूल तत्वों को परिवर्तित किए बिना एक तत्व का पाठ कैसे बदल सकता / सकती हूं? मैं C ++ में एरेज़ का उपयोग कैसे करूं? रूबी में अवरोही क्रम में एक सरणी को क्रमबद्ध करना स्वत: पूर्ण दृश्य स्टूडियो में काम नहीं कर रहा है क्या मैं जेडीबीसी कनेक्शन पूलिंग का उपयोग कर रहा हूं?

एक्स-मैक्रोज का असली दुनिया का उपयोग

मैं बस एक्स-मैक्रोज़ का सीखा क्या आपने एक्स-मैक्रोज का वास्तविक दुनिया उपयोग किया है? वे नौकरी के लिए सही उपकरण कब हैं?

वेब के समाधान से एकत्रित समाधान "एक्स-मैक्रोज का असली दुनिया का उपयोग"

मैंने कुछ साल पहले एक्स-मैक्रोज़ की खोज की थी जब मैंने अपने कोड में फ़ंक्शन पॉइंटर्स का उपयोग करना शुरू कर दिया था। मैं एक एम्बेडेड प्रोग्रामर हूँ और मैं अक्सर राज्य मशीनों का उपयोग करता हूं। अक्सर मैं इस तरह से कोड लिखूंगा:

/* declare an enumeration of state codes */ enum{ STATE0, STATE1, STATE2, ... , STATEX, NUM_STATES}; /* declare a table of function pointers */ p_func_t jumptable[NUM_STATES] = {func0, func1, func2, ... , funcX}; 

समस्या यह थी कि मैंने इसे बहुत त्रुटि प्रवणता के रूप में माना है कि मेरे फ़ंक्शन पॉइन्टर टेबल को क्रमबद्ध रखने के लिए यह मेरे राज्यों की गणना के अनुरूप है।

मेरा एक मित्र ने एक्स-मैक्रोज़ में मुझे पेश किया और यह मेरे सिर में एक प्रकाश बल्ब की तरह था। गंभीरता से, तुम मेरी सारी जिंदगी X-macros कहाँ रही हो!

तो अब मैं निम्नलिखित तालिका को परिभाषित करता हूं:

 #define STATE_TABLE \ ENTRY(STATE0, func0) \ ENTRY(STATE1, func1) \ ENTRY(STATE2, func2) \ ... ENTRY(STATEX, funcX) \ 

और मैं इसका उपयोग निम्नानुसार कर सकता हूँ:

 enum { #define ENTRY(a,b) a, STATE_TABLE #undef ENTRY NUM_STATES }; 

तथा

 p_func_t jumptable[NUM_STATES] = { #define ENTRY(a,b) b, STATE_TABLE #undef ENTRY }; 

एक बोनस के रूप में, मैं पूर्व-प्रोसेसर को भी अपने कार्य प्रोटोटाइप का निर्माण कर सकता हूं:

 #define ENTRY(a,b) static void b(void); STATE_TABLE #undef ENTRY 

एक अन्य उपयोग रजिस्टरों को घोषित और आरम्भ करना है

 #define IO_ADDRESS_OFFSET (0x8000) #define REGISTER_TABLE\ ENTRY(reg0, IO_ADDRESS_OFFSET + 0, 0x11)\ ENTRY(reg1, IO_ADDRESS_OFFSET + 1, 0x55)\ ENTRY(reg2, IO_ADDRESS_OFFSET + 2, 0x1b)\ ... ENTRY(regX, IO_ADDRESS_OFFSET + X, 0x33)\ /* declare the registers (where _at_ is a compiler specific directive) */ #define ENTRY(a, b, c) volatile uint8_t a _at_ b: REGISTER_TABLE #undef ENTRY /* initialize registers */ #define ENTRY(a, b, c) a = c; REGISTER_TABLE #undef ENTRY 

मेरा पसंदीदा उपयोग तब होता है जब यह संचार संचालकों की बात आती है

सबसे पहले मैं एक कॉमिक्स टेबल बनाऊँ, जिसमें प्रत्येक कमांड का नाम और कोड होता है:

 #define COMMAND_TABLE \ ENTRY(RESERVED, reserved, 0x00) \ ENTRY(COMMAND1, command1, 0x01) \ ENTRY(COMMAND2, command2, 0x02) \ ... ENTRY(COMMANDX, commandX, 0x0X) \ 

मेरे पास तालिका में अपरकेस और लोअरकेस नाम दोनों हैं, क्योंकि ऊपरी केस को एन्हों और फ़ंक्शन नामों के लिए लोअरकेस के लिए उपयोग किया जाएगा।

तब मैं प्रत्येक आदेश के लिए structs को परिभाषित भी करता हूं कि ये परिभाषित करने के लिए कि प्रत्येक कमांड कैसा दिखता है:

 typedef struct {...}command1_cmd_t; typedef struct {...}command2_cmd_t; etc. 

इसी तरह मैं प्रत्येक आदेश प्रतिक्रिया के लिए स्ट्रैक्ट्स को परिभाषित करता हूं:

 typedef struct {...}command1_resp_t; typedef struct {...}command2_resp_t; etc. 

फिर मैं अपने कमांड कोड गणन को परिभाषित कर सकता हूं:

 enum { #define ENTRY(a,b,c) a##_CMD = c, COMMAND_TABLE #undef ENTRY }; 

मैं अपनी कमान लंबाई लंबाई को परिभाषित कर सकता हूँ:

 enum { #define ENTRY(a,b,c) a##_CMD_LENGTH = sizeof(b##_cmd_t); COMMAND_TABLE #undef ENTRY }; 

मैं अपनी प्रतिक्रिया की लंबाई को परिभाषित कर सकता हूं:

 enum { #define ENTRY(a,b,c) a##_RESP_LENGTH = sizeof(b##_resp_t); COMMAND_TABLE #undef ENTRY }; 

मैं निर्धारित कर सकता हूँ कि निम्नानुसार कितने कमांड हैं:

 typedef struct { #define ENTRY(a,b,c) uint8_t b; COMMAND_TABLE #undef ENTRY } offset_struct_t; #define NUMBER_OF_COMMANDS sizeof(offset_struct_t) 

नोट: मैं कभी भी offset_struct_t इन्स्तांत नहीं, मैं सिर्फ संकलक के लिए मेरे लिए आदेश परिभाषा की मेरी संख्या उत्पन्न करने के लिए एक रास्ता के रूप में इसका इस्तेमाल करते हैं

नोट करें तो मैं निम्न के रूप में फ़ंक्शन पॉइंटर्स की मेरी तालिका उत्पन्न कर सकता हूं:

 p_func_t jump_table[NUMBER_OF_COMMANDS] = { #define ENTRY(a,b,c) process_##b, COMMAND_TABLE #undef ENTRY } 

और मेरा फ़ंक्शन प्रोटोटाइप:

 #define ENTRY(a,b,c) void process_##b(void); COMMAND_TABLE #undef ENTRY 

अब अंततः सबसे अच्छे उपयोग के लिए, मैं संकलक को गणना कर सकता हूं कि मेरे संचारित बफर कितने बड़े होंगे।

 /* reminder the sizeof a union is the size of its largest member */ typedef union { #define ENTRY(a,b,c) uint8_t b##_buf[sizeof(b##_cmd_t)]; COMMAND_TABLE #undef ENTRY }tx_buf_t 

फिर से यह संघ मेरे ऑफ़सेट स्ट्रैट की तरह है, इसे तत्काल नहीं किया गया है, इसके बजाय मैं आकार के ऑपरेटर का उपयोग अपने ट्रांसमिट बफर आकार को घोषित करने के लिए कर सकता हूं।

 uint8_t tx_buf[sizeof(tx_buf_t)]; 

अब मेरे संचारित बफर टीएक्स_बुफ़ इष्टतम आकार है और जैसा कि मैं इस कॉमिक्स हैंडलर को कमांड जोड़ता हूं, मेरा बफर हमेशा इष्टतम आकार होगा। ठंडा!

एक अन्य उपयोग ऑफसेट टेबल बनाने के लिए है: चूंकि मेमोरी अक्सर एम्बेडेड सिस्टम पर एक बाधा है, इसलिए मैं अपनी कूद तालिका (2 बाइट्स प्रति सूचक एक्स 256 संभावित कमांड) के लिए 512 बाइट्स का उपयोग नहीं करना चाहता, जब यह एक विरल सरणी होता है इसके बजाय मेरे पास प्रत्येक संभव कमांड के लिए 8 बिट ऑफ़सेट्स की एक तालिका होगी। यह ऑफसेट तब मेरी वास्तविक कूद तालिका में अनुक्रमणिका के लिए प्रयोग किया जाता है, जिसे अब केवल NUM_COMMANDS * आकार (पॉइंटर) की आवश्यकता है। मेरे मामले में 10 आज्ञाओं के साथ परिभाषित मेरी कूद तालिका 20bytes लंबी है और मेरे पास एक ऑफसेट टेबल है जो 256 बाइट्स लंबा है, जो 512bytes के बजाय कुल 276bytes है। तब मैं अपने कार्यों को इसी तरह फोन करता हूं:

 jump_table[offset_table[command]](); 

के बजाय

 jump_table[command](); 

मैं इस तरह एक ऑफसेट तालिका बना सकता हूं:

 /* initialize every offset to 0 */ static uint8_t offset_table[256] = {0}; /* for each valid command, initialize the corresponding offset */ #define ENTRY(a,b,c) offset_table[c] = offsetof(offset_struct_t, b); COMMAND_TABLE #undef ENTRY 

जहां offsetof एक मानक पुस्तकालय "stddef.h" में परिभाषित मैक्रो है

पक्ष लाभ के रूप में, यह तय करने का एक आसान तरीका है कि कमांड कोड समर्थित है या नहीं:

 bool command_is_valid(uint8_t command) { /* return false if not valid, or true (non 0) if valid */ return offset_table[command]; } 

यह भी मेरे COMMAND_TABLE में कमांड बाइट 0 में आरक्षित क्यों है। मैं "प्रोसेस_रेबिलक्षित ()" नामक एक फ़ंक्शन बना सकता हूं, जिसे कहा जाएगा कि कोई अमान्य आदेश बाइट मेरे ऑफसेट तालिका में इंडेक्स के लिए उपयोग किया जाता है।

एक्स-मैक्रोज़ अनिवार्य रूप से पैरामीटरबद्ध टेम्पलेट हैं इसलिए यदि आप कई ढलानों में कई समान चीजों की ज़रूरत हैं तो वे नौकरी के लिए सही उपकरण हैं। वे आपको एक अमूर्त प्रपत्र बनाने और इसे विभिन्न नियमों के अनुसार इन्स्तांत करने की अनुमति देते हैं।

मैं स्ट्रोब के रूप में आउटपुट एन्यूम मानों के लिए एक्स-मैक्रोज का उपयोग करता हूं। और इसका सामना करने के बाद, मैं दृढ़ता से इस प्रपत्र को पसंद करता हूं जो प्रत्येक तत्व पर लागू करने के लिए "उपयोगकर्ता" मैक्रो लेता है। एकाधिक फ़ाइल शामिल करने के साथ काम करने के लिए अभी तक अधिक दर्दनाक है।

 /* x-macro constructors for error and type enums and string tables */ #define AS_BARE(a) a , #define AS_STR(a) #a , #define ERRORS(_) \ _(noerror) \ _(dictfull) _(dictstackoverflow) _(dictstackunderflow) \ _(execstackoverflow) _(execstackunderflow) _(limitcheck) \ _(VMerror) enum err { ERRORS(AS_BARE) }; char *errorname[] = { ERRORS(AS_STR) }; /* puts(errorname[(enum err)limitcheck]); */ 

मैं ऑब्जेक्ट प्रकार के आधार पर फ़ंक्शन डिस्पैच के लिए भी उनका उपयोग कर रहा हूं। फिर से एक ही मैक्रो अपहरण करके मैं एन्यूम मूल्यों को बनाने के लिए इस्तेमाल किया।

 #define TYPES(_) \ _(invalid) \ _(null) \ _(mark) \ _(integer) \ _(real) \ _(array) \ _(dict) \ _(save) \ _(name) \ _(string) \ /*enddef TYPES */ #define AS_TYPE(_) _ ## type , enum { TYPES(AS_TYPE) }; 

मैक्रो की गारंटी देता है कि मेरे सारे सरणी इंडेक्स संबद्ध एएनआईम मानों से मेल खाएंगे, क्योंकि वे मेक्रो परिभाषा (टाईपे मैक्रो) से नंगे टोकन का उपयोग करके अपने विभिन्न रूपों का निर्माण करते हैं।

 typedef void evalfunc(context *ctx); void evalquit(context *ctx) { ++ctx->quit; } void evalpop(context *ctx) { (void)pop(ctx->lo, adrent(ctx->lo, OS)); } void evalpush(context *ctx) { push(ctx->lo, adrent(ctx->lo, OS), pop(ctx->lo, adrent(ctx->lo, ES))); } evalfunc *evalinvalid = evalquit; evalfunc *evalmark = evalpop; evalfunc *evalnull = evalpop; evalfunc *evalinteger = evalpush; evalfunc *evalreal = evalpush; evalfunc *evalsave = evalpush; evalfunc *evaldict = evalpush; evalfunc *evalstring = evalpush; evalfunc *evalname = evalpush; evalfunc *evaltype[stringtype/*last type in enum*/+1]; #define AS_EVALINIT(_) evaltype[_ ## type] = eval ## _ ; void initevaltype(void) { TYPES(AS_EVALINIT) } void eval(context *ctx) { unsigned ades = adrent(ctx->lo, ES); object t = top(ctx->lo, ades, 0); if ( isx(t) ) /* if executable */ evaltype[type(t)](ctx); /* <--- the payoff is this line here! */ else evalpush(ctx); } 

X-macros का उपयोग करना इस तरह से वास्तव में उपयोगी त्रुटि संदेश देने के लिए संकलक को मदद करता है। मैंने ऊपर से evalarray समारोह छोड़ा क्योंकि यह मेरे बिंदु से विचलित होगा परन्तु यदि आप उपरोक्त कोड को संकलित करने का प्रयास करते हैं (अन्य फ़ंक्शन कॉल करने की सलाह देते हैं, और संदर्भ के लिए एक डमी टाइपिंगफेप प्रदान करते हैं), तो कंपाइलर एक गायब समारोह के बारे में शिकायत करेगा। प्रत्येक नए प्रकार के लिए मैं जोड़ता हूं, मुझे याद दिलाया जाता है कि जब मैं इस मॉड्यूल को पुनः कंपाइल करता हूं, तो एक हैंडलर जोड़ने के लिए। इसलिए एक्स-मैक्रो गारंटी देने में मदद करता है कि समानांतर संरचनाएं बरकरार रहें, जैसे कि परियोजना बढ़ती जा रही है।

संपादित करें:

इस उत्तर ने मेरी प्रतिष्ठा 50% बढ़ा दी है। तो यहाँ थोड़ा और अधिक है निम्नलिखित प्रश्न का उत्तर देने वाला एक नकारात्मक उदाहरण है : एक्स-मैक्रोज का प्रयोग करने पर?

यह उदाहरण एक्स-"रिकॉर्ड" में मनमानी कोड के टुकड़ों को पैकिंग दिखाता है मैंने अंततः परियोजना की इस शाखा को त्याग दिया और बाद में डिजाइनों में इस रणनीति का उपयोग नहीं किया (और कोशिश करने की इच्छा के लिए नहीं) यह अविवेकी हो गया, किसी तरह वास्तव में मैक्रो का नाम एक्स 6 है क्योंकि एक बिंदु पर 6 तर्क थे, लेकिन मैक्रो नाम बदलने के थक गए।

 /* Object types */ /* "'X'" macros for Object type definitions, declarations and initializers */ // abcd // enum, string, union member, printf d #define OBJECT_TYPES \ X6( nulltype, "null", int dummy , ("<null>")) \ X6( marktype, "mark", int dummy2 , ("<mark>")) \ X6( integertype, "integer", int i, ("%d",oi)) \ X6( booleantype, "boolean", bool b, (ob?"true":"false")) \ X6( realtype, "real", float f, ("%f",of)) \ X6( nametype, "name", int n, ("%s%s", \ (o.flags & Fxflag)?"":"/", names[on])) \ X6( stringtype, "string", char *s, ("%s",os)) \ X6( filetype, "file", FILE *file, ("<file %p>",(void *)o.file)) \ X6( arraytype, "array", Object *a, ("<array %u>",o.length)) \ X6( dicttype, "dict", struct s_pair *d, ("<dict %u>",o.length)) \ X6(operatortype, "operator", void (*o)(), ("<op>")) \ #define X6(a, b, c, d) #a, char *typestring[] = { OBJECT_TYPES }; #undef X6 // the Object type //forward reference so s_object can contain s_objects typedef struct s_object Object; // the s_object structure: // a bit convoluted, but it boils down to four members: // type, flags, length, and payload (union of type-specific data) // the first named union member is integer, so a simple literal object // can be created on the fly: // Object o = {integertype,0,0,4028}; //create an int object, value: 4028 // Object nl = {nulltype,0,0,0}; struct s_object { #define X6(a, b, c, d) a, enum e_type { OBJECT_TYPES } type; #undef X6 unsigned int flags; #define Fread 1 #define Fwrite 2 #define Fexec 4 #define Fxflag 8 size_t length; //for lint, was: unsigned int #define X6(a, b, c, d) c; union { OBJECT_TYPES }; #undef X6 }; 

एक बड़ी समस्या printf प्रारूप स्ट्रिंग थी। हालांकि यह अच्छा लगता है, यह सिर्फ फोकस पोकस है चूंकि यह केवल एक फ़ंक्शन में उपयोग किया जाता है, मैक्रो का अति प्रयोग वास्तव में जानकारी को अलग करता है जो एक साथ होना चाहिए; और यह फ़ंक्शन स्वयं द्वारा अपठनीय बनाता है। इस तरह एक डीबगिंग फ़ंक्शन में ओब्फीसकेशन दोगुना दुर्भाग्यपूर्ण है

 //print the object using the type's format specifier from the macro //used by O_equal (ps: =) and O_equalequal (ps: ==) void printobject(Object o) { switch (o.type) { #define X6(a, b, c, d) \ case a: printf d; break; OBJECT_TYPES #undef X6 } } 

तो दूर नहीं ले जाओ। जैसे मैंने किया।

जावा प्रोग्रामिंग भाषा के लिए ओरेकल हॉटस्पॉट वर्चुअल मशीन में, फ़ाइल globals.hpp , जो इस तरह से RUNTIME_FLAGS का उपयोग करता है

स्रोत कोड देखें:

  • जेडीके 7
  • जेडीके 8
  • जेडीके 9

मैं 'समृद्ध एन्यूमरेशन' बनाने के लिए एक्स मैक्रोज़ का उपयोग करना चाहता हूं जो एनाम मानों के साथ-साथ प्रत्येक एनाम वैल्यू के लिए स्ट्रिंग प्रस्तुति को प्राप्त करने का समर्थन करता है:

 #define MOUSE_BUTTONS \ X(LeftButton, 1) \ X(MiddleButton, 2) \ X(RightButton, 4) struct MouseButton { enum Value { None = 0 #define X(name, value) ,name = value MOUSE_BUTTONS #undef X }; static const int *values() { static const int a[] = { None, #define X(name, value) name, MOUSE_BUTTONS #undef X -1 }; return a; } static const char *valueAsString( Value v ) { #define X(name, value) static const char str_##name[] = #name; MOUSE_BUTTONS #undef X switch ( v ) { case None: return "None"; #define X(name, value) case name: return str_##name; MOUSE_BUTTONS #undef X } return 0; } }; 

यह न केवल MouseButton::Value enum को परिभाषित करता है, यह मुझे कुछ भी करने की सुविधा देता है

 // Print names of all supported mouse buttons for ( const int *mb = MouseButton::values(); *mb != -1; ++mb ) { std::cout << MouseButton::valueAsString( (MouseButton::Value)*mb ) << "\n"; } 

मैं INI- फाइल की सामग्री को एक संरचनात्मक संरचना में लोड करने के लिए एक बहुत बड़े एक्स-मैक्रो का उपयोग करता हूं, जिसमें उस संरचना के आसपास घूमते हुए अन्य चीजों के बीच।

यह मेरा "configuration.def" -file ऐसा दिखता है:

 #define NMB_DUMMY(...) X(__VA_ARGS__) #define NMB_INT_DEFS \ TEXT("long int") , long , , , GetLongValue , _ttol , NMB_SECT , SetLongValue , #define NMB_STR_DEFS NMB_STR_DEFS__(TEXT("string")) #define NMB_PATH_DEFS NMB_STR_DEFS__(TEXT("path")) #define NMB_STR_DEFS__(ATYPE) \ ATYPE , basic_string<TCHAR>* , new basic_string<TCHAR>\ , delete , GetValue , , NMB_SECT , SetValue , * /* X-macro starts here */ #define NMB_SECT "server" NMB_DUMMY(ip,TEXT("Slave IP."),TEXT("10.11.180.102"),NMB_STR_DEFS) NMB_DUMMY(port,TEXT("Slave portti."),TEXT("502"),NMB_STR_DEFS) NMB_DUMMY(slaveid,TEXT("Slave protocol ID."),0xff,NMB_INT_DEFS) . . /* And so on for about 40 items. */ 

यह थोड़ा भ्रमित है, मैं स्वीकार करता हूं यह जल्दी से स्पष्ट हो गया कि मैं वास्तव में उन सभी प्रकार की घोषणाओं को प्रत्येक फ़ील्ड-मैक्रो के बाद लिखना नहीं चाहता। (चिंता न करें, संक्षेप के लिए जो कुछ भी मैंने छोड़ा है उसे समझाने के लिए एक बड़ी टिप्पणी है।)

और इस तरह से मैं विन्यास संरचना की घोषणा करता हूं:

 typedef struct { #define X(ID,DESC,DEFVAL,ATYPE,TYPE,...) TYPE ID; #include "configuration.def" #undef X basic_string<TCHAR>* ini_path; //Where all the other stuff gets read. long verbosity; //Used only by console writing functions. } Config; 

फिर, कोड में, सबसे पहले डिफ़ॉल्ट मान को कॉन्फ़िगरेशन स्ट्रेट में पढ़ा जाता है:

 #define X(ID,DESC,DEFVAL,ATYPE,TYPE,CONSTRUCTOR,DESTRUCTOR,GETTER,STRCONV,SECT,SETTER,...) \ conf->ID = CONSTRUCTOR(DEFVAL); #include "configuration.def" #undef X 

इसके बाद, INI को विन्यास संरचना में पढ़ा जाता है, इस प्रकार लाइब्रेरी SimpleIni का उपयोग करते हुए:

 #define X(ID,DESC,DEFVAL,ATYPE,TYPE,CONSTRUCTOR,DESTRUCTOR,GETTER,STRCONV,SECT,SETTER,DEREF...)\ DESTRUCTOR (conf->ID);\ conf->ID = CONSTRUCTOR( ini.GETTER(TEXT(SECT),TEXT(#ID),DEFVAL,FALSE) );\ LOG3A(<< left << setw(13) << TEXT(#ID) << TEXT(": ") << left << setw(30)\ << DEREF conf->ID << TEXT(" (") << DEFVAL << TEXT(").") ); #include "configuration.def" #undef X 

और कमांडलाइन फ्लैग से ओवरराइड करता है, जो उसी नामों (जीएनयू लम्बी फॉर्म में) के साथ स्वरूपित होते हैं, लायब्रेरी के उपयोग के तरीके के रूप में निम्नानुसार लागू होते हैं SimpleOpt:

 enum optflags { #define X(ID,...) ID, #include "configuration.def" #undef X }; CSimpleOpt::SOption sopt[] = { #define X(ID,DESC,DEFVAL,ATYPE,TYPE,...) {ID,TEXT("--") #ID TEXT("="), SO_REQ_CMB}, #include "configuration.def" #undef X SO_END_OF_OPTIONS }; CSimpleOpt ops(argc,argv,sopt,SO_O_NOERR); while(ops.Next()){ switch(ops.OptionId()){ #define X(ID,DESC,DEFVAL,ATYPE,TYPE,CONSTRUCTOR,DESTRUCTOR,GETTER,STRCONV,SECT,...) \ case ID:\ DESTRUCTOR (conf->ID);\ conf->ID = STRCONV( CONSTRUCTOR ( ops.OptionArg() ) );\ LOG3A(<< TEXT("Omitted ")<<left<<setw(13)<<TEXT(#ID)<<TEXT(" : ")<<conf->ID<<TEXT(" ."));\ break; #include "configuration.def" #undef X } } 

और इसी तरह, मैं –help -flag output और sample default ini फ़ाइल को प्रिंट करने के लिए एक ही मैक्रो का उपयोग भी करता हूं, configuration.def मेरे प्रोग्राम में 8 बार शामिल है। "एक गोल छेद में स्क्वायर पेग", शायद; वास्तव में सक्षम प्रोग्रामर इस के साथ कैसे आगे बढ़ेंगे? बहुत सारे और बहुत सारे loops और स्ट्रिंग प्रसंस्करण?

https://github.com/whunmr/DataEx

एक सी + + क्लास उत्पन्न करने के लिए निम्नलिखित xmacros का उपयोग करते हुए, फ़्रीक्लेटीआई निर्मित में सीरियललाइज़ और डिसेरीलाइज़ करना।

 #define __FIELDS_OF_DataWithNested(_) \ _(1, a, int ) \ _(2, x, DataX) \ _(3, b, int ) \ _(4, c, char ) \ _(5, d, __array(char, 3)) \ _(6, e, string) \ _(7, f, bool) DEF_DATA(DataWithNested); 

उपयोग:

 TEST_F(t, DataWithNested_should_able_to_encode_struct_with_nested_struct) { DataWithNested xn; xn.a = 0xCAFEBABE; xn.xa = 0x12345678; xn.xb = 0x11223344; xn.b = 0xDEADBEEF; xn.c = 0x45; memcpy(&xn.d, "XYZ", strlen("XYZ")); char buf_with_zero[] = {0x11, 0x22, 0x00, 0x00, 0x33}; xn.e = string(buf_with_zero, sizeof(buf_with_zero)); xn.f = true; __encode(DataWithNested, xn, buf_); char expected[] = { 0x01, 0x04, 0x00, 0xBE, 0xBA, 0xFE, 0xCA , 0x02, 0x0E, 0x00 /*T and L of nested X*/ , 0x01, 0x04, 0x00, 0x78, 0x56, 0x34, 0x12 , 0x02, 0x04, 0x00, 0x44, 0x33, 0x22, 0x11 , 0x03, 0x04, 0x00, 0xEF, 0xBE, 0xAD, 0xDE , 0x04, 0x01, 0x00, 0x45 , 0x05, 0x03, 0x00, 'X', 'Y', 'Z' , 0x06, 0x05, 0x00, 0x11, 0x22, 0x00, 0x00, 0x33 , 0x07, 0x01, 0x00, 0x01}; EXPECT_TRUE(ArraysMatch(expected, buf_)); } 

यह भी एक और उदाहरण है https://github.com/whunmr/msgrpc