2011-05-10 21 views
10

मेरा अनुमान है कि इस सवाल का जवाब नहीं है, लेकिन अगर कोई रास्ता था तो यह शानदार होगा। स्पष्ट करने के लिए, मान लें कि मैं निम्नलिखित मैक्रो है:क्या वैरिएडिक मैक्रो तर्कों पर सी ++ प्रीप्रोसेसर स्ट्रिंग का उपयोग करने का कोई तरीका है?

#define MY_VARIADIC_MACRO(X...) // Does some stuff here in the macro definition 

मुझे क्या करना चाहते हैं किसी भी तरह है यह एक variadic कार्य करने के लिए पारित करने से पहले एक्स के सभी चर पर stringification करते हैं; यहां कीवर्ड पहले है। मुझे एहसास है कि मैक्रो परिभाषा के भीतर से व्यक्तिगत तर्कों को वास्तव में एक्सेस करने का कोई तरीका नहीं है, लेकिन क्या निम्न तर्कों के साथ सभी तर्कों को स्ट्रिंग करने का कोई तरीका है?

#define MY_VARIADIC_MACRO(X...) some_variadic_function("some string", #X) 

उत्तर

8

ठीक है, मेरा मतलब यहां मेरे अपने प्रश्न का उत्तर देने का नहीं था, लेकिन मैं एक सभ्य समाधान के साथ आया हूं जो मार्क विल्किन्स के उत्तर और उदाहरण में मैंने जो उदाहरण दिया है, उसका संयोजन है।

पूरे सेट वैरिएडिक सेट को स्ट्रिंग करना संभव है, जिसमें स्ट्रिंग में सीमित कमांड शामिल हैं। यहां एक त्वरित उदाहरण है:

#define MY_VARIADIC_MACRO(X...) printf(#X) 

ऊपर मैक्रो का उपयोग करके आप पता चलता है कि मैक्रो के लिए पारित तर्क के पूरे सेट stringified हो जाता है।

तो फिर तुम तो variadic मैक्रो का उपयोग करके इन परिसीमन अल्पविराम का उपयोग कर, जिससे tokenized तार के सेट हो रही बहस tokenize करने के लिए एक समारोह को परिभाषित कर सकते हैं:

#define MY_VARIADIC_MACRO(X...) tokenize_my_arguments(#X) 

तो फिर वहाँ वास्तव में नहीं रह गया है होने की निर्भरता है वैरैडिक मैक्रो एक वैरैडिक फ़ंक्शन कॉल करता है और मैं va_arg के माध्यम से फिर से चलने के बजाय निरंतर सी तारों की मेरी सरणी के माध्यम से अच्छी तरह से पुन: सक्रिय कर सकता हूं।

संपादित से * नई सामग्री का पालन करता *

प्रति टिम टिप्पणी, यहाँ समाधान का ब्यौरा है। कृपया किसी भी त्रुटि को क्षमा करें क्योंकि यह जल्दबाजी में किया गया था और मुझे जो काम कर रहा हूं उससे बंदरगाह करना पड़ा। इसके अलावा, यह प्रतिलिपि/पेस्ट समाधान नहीं है क्योंकि यह केवल पीओसी को प्रदर्शित करने के लिए तर्कों के स्ट्रिंगफिकेशन को आउटपुट करता है, लेकिन कार्यक्षमता का प्रदर्शन करने के लिए पर्याप्त होना चाहिए।

हालांकि इस समाधान के लिए कुछ रन टाइम गणना की आवश्यकता है, वैरिएडिक मैक्रोज़ अक्सर बार-बार भिन्नता वाले कार्यों को कॉल करते हैं और va_args के माध्यम से पुनरावृत्ति की आवश्यकता होती है, इसलिए टोकन को खोजने में पुनरावृत्ति होती है, हालांकि थोड़ा सा प्रदर्शन शायद बलिदान किया जाता है।

#define VARIADIC_STRINGIFY(_ARGUMENTS_TO_STRINGIFY...) Variadic_Stringification_Without_Variadic_Function(#_ARGUMENTS_TO_STRINGIFY) 

void Variadic_Stringification_Without_Variadic_Function (const char* _stringified_arguments) 
{ 
    strcpy(converted_arguments, _stringified_arguments); 

    for(char* token = strtok(converted_arguments, ","); token != 0x0; token = strtok(0x0, ",")) 
     std::cout << token << std::endl; 
} 
+0

इसके अलावा, इस की एक और अच्छी विशेषता यह है कि सूची में तर्क कहां समाप्त होता है यह निर्धारित करने के लिए मैक्रो के माध्यम से कुछ प्रकार की जानकारी पारित किए बिना मुझे आसानी से तर्कों की संख्या मिल सकती है। – Hazok

+0

दिलचस्प है, लेकिन इससे पहले कि आप इसे समाधान के रूप में चिह्नित करें, अपना वास्तविक कोड पोस्ट करें जो इसे हल करता है। मुझे यकीन है कि यह दूसरों के लिए आसान होगा। – Tim

+0

@ टिम विल, मैं पहले से ही एक साधारण मामला का परीक्षण कर चुका हूं और इसे एक अच्छा उदाहरण बनाउंगा ... कुछ समय सीमाएं हैं और कल (5/11/2011) या अगले दिन पोस्ट करेंगे। – Hazok

2

यह शायद बहुत आप क्या चाहते हैं कर रहे हैं के पास नहीं है, लेकिन निम्नलिखित की तरह कुछ तुम वहाँ मिल सकता है:

#define MY_VARIADIC_MACRO(X) printf("%s\n", #X) 

उसके बाद निम्न की तरह उपयोग। माता-पिता में पैरामीटर संलग्न करें ताकि यह मैक्रो के लिए एक पैरामीटर के रूप में दिखाई दे।

MY_VARIADIC_MACRO ((var1, var2, "string"));

तब आप मैक्रो को कुछ फ़ंक्शन को कॉल कर सकते हैं जो बाहरी माता-पिता को स्ट्रिप्स करता है या संभवतः दिए गए स्ट्रिंग को पार करता है।

+0

कि लगभग वहाँ है, लेकिन विचार टी को राहत देने है उसे कोष्ठक को घेरने की जरूरत है ... डर्न रिटर्न त्वरित टिप्पणी को जोड़ता है, शिफ्ट-रिटर्न को याद रखने की आवश्यकता है। मुझे लगता है कि उपर्युक्त समाधान के बहुत करीब है, हालांकि मैं इसके प्रति काम कर रहा हूं। मैं इस जवाब को वोट दूंगा क्योंकि यह लगभग है, लेकिन इसे मुख्य उत्तर के रूप में चिह्नित नहीं किया जा सकता क्योंकि यह आवश्यकताओं को पूरी तरह से संतुष्ट नहीं करता है। – Hazok

+0

@Zach: मैंने अनुमान लगाया है। मुझे यह देखना अच्छा लगेगा कि यह कैसे किया जा सकता है। मेरी समझ यह है कि यह संभव नहीं है, लेकिन मैं अलग दिखाना चाहता हूं। –

+0

मैंने उपरोक्त उत्तर पोस्ट किया है कि मैं इसके साथ जाने के लिए जा रहा हूं, मेरे सामने आने वाले मुद्दों में से एक बहुत हल करता है। – Hazok

18

आप विभिन्न पुनरावर्ती मैक्रो तकनीक का उपयोग कर सकते variadic मैक्रो के साथ काम करने के लिए: हालांकि, रख-रखाव, बहुमुखी प्रतिभा, और कार्यान्वयन में आसानी के लिए, इस समय सबसे अच्छा विकल्प हो रहा है। उदाहरण के लिए, यदि आप एक NUM_ARGS मैक्रो कि एक variadic मैक्रो को तर्क की संख्या की गणना को परिभाषित कर सकते हैं:

#define _NUM_ARGS(X100, X99, X98, X97, X96, X95, X94, X93, X92, X91, X90, X89, X88, X87, X86, X85, X84, X83, X82, X81, X80, X79, X78, X77, X76, X75, X74, X73, X72, X71, X70, X69, X68, X67, X66, X65, X64, X63, X62, X61, X60, X59, X58, X57, X56, X55, X54, X53, X52, X51, X50, X49, X48, X47, X46, X45, X44, X43, X42, X41, X40, X39, X38, X37, X36, X35, X34, X33, X32, X31, X30, X29, X28, X27, X26, X25, X24, X23, X22, X21, X20, X19, X18, X17, X16, X15, X14, X13, X12, X11, X10, X9, X8, X7, X6, X5, X4, X3, X2, X1, N, ...) N 

#define NUM_ARGS(...) _NUM_ARGS(__VA_ARGS__, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) 

उस के साथ फिर, आप एक FOREACH मैक्रो एक सूची के प्रत्येक तत्व के लिए एक और मैक्रो का विस्तार लिख सकते हैं:

#define EXPAND(X)  X 
#define FIRSTARG(X, ...) (X) 
#define RESTARGS(X, ...) (__VA_ARGS__) 
#define FOREACH(MACRO, LIST) FOREACH_(NUM_ARGS LIST, MACRO, LIST) 
#define FOREACH_(N, M, LIST) FOREACH__(N, M, LIST) 
#define FOREACH__(N, M, LIST) FOREACH_##N(M, LIST) 
#define FOREACH_1(M, LIST) M LIST 
#define FOREACH_2(M, LIST) EXPAND(M FIRSTARG LIST) FOREACH_1(M, RESTARGS LIST) 
#define FOREACH_3(M, LIST) EXPAND(M FIRSTARG LIST) FOREACH_2(M, RESTARGS LIST) 
     : 

जिससे फिर आपको अपने मैक्रो कि अपने तर्कों से प्रत्येक stringifies को परिभाषित करने के लिए अनुमति देगा:

#define STRINGIFY(X) #X 
#define MY_VARIADIC_MACRO(...) FOREACH(STRINGIFY, (__VA_ARGS__)) 
+0

मुझे उन पुनरावर्ती तकनीकों के बारे में पता है, लेकिन जैसा कि ऊपर से देखा गया है वे थके हुए हैं और उनके पास दुर्भाग्यपूर्ण प्रतिबंध भी है कि आप संकलन समय पर आपके द्वारा दर्ज किए गए तर्कों की संख्या तक ही सीमित हैं। मैं जल्द ही उस समाधान के विवरण के साथ अपना उत्तर अपडेट करूंगा जो कार्यान्वित करने के लिए कठिन नहीं है और यह एक पूर्वनिर्धारित अधिकतम तक सीमित नहीं है जो बनाए रखना आसान है। यह सभी मामलों के लिए सबसे अच्छा समाधान हो सकता है, लेकिन मुझे जो चाहिए वह इसके लिए ऊपर से बेहतर जवाब है। वैसे, इनपुट के लिए धन्यवाद! – Hazok

संबंधित मुद्दे