C & C ++ (अपडेट किया गया उत्तर)
जैसा कि एक टिप्पणी में देखा गया, मेरे मूल समाधान में दो समस्याएं थीं:
- वैकल्पिक पैरामीटर केवल C99 और बाद के भाषा परिवार के मानकों में उपलब्ध हैं।
- Enum परिभाषा में ट्रेलिंग कॉमा भी C99 और बाद के लिए विशिष्ट है।
चूंकि मैं चाहता था कि मेरा कोड पुराने प्लेटफार्मों पर काम करने के लिए जितना संभव हो उतना सामान्य हो, मैंने इसे एक और छुरा लेने का फैसला किया। यह पहले की तुलना में लंबा है, लेकिन यह C89 / C90 संगतता मोड पर सेट किए गए कंपाइलर और प्रीप्रोसेसर पर काम करता है। सभी मैक्रोज़ को स्रोत कोड में उपयुक्त संख्या में तर्क दिए गए हैं, हालांकि कभी-कभी वे मैक्रोज़ "विस्तार" कुछ नहीं करते हैं।
दृश्य C ++ 2013 (उर्फ संस्करण 12) लापता मापदंडों के बारे में चेतावनी देता है, लेकिन न तो mcpp (एक खुला स्रोत प्रीप्रोसेसर जो मानक के उच्च अनुपालन का दावा करता है) और न ही 4.8.1.1 (-std = iso9899 के साथ: 1990-थप्टैटिक-एरर स्विच) एक प्रभावी खाली तर्क सूची के साथ उन मैक्रो इनवोकेशन के लिए चेतावनी या त्रुटियां।
प्रासंगिक मानक (ANSI / ISO 9899-1990, 6.8.3, मैक्रो रिप्लेसमेंट) की समीक्षा करने के बाद, मुझे लगता है कि पर्याप्त अस्पष्टता है कि इसे गैर-मानक नहीं माना जाना चाहिए। "एक फ़ंक्शन-जैसे मैक्रो के आह्वान में तर्कों की संख्या मैक्रो परिभाषा में मापदंडों की संख्या से सहमत होगी ..."। जब तक मैक्रो को लागू करने के लिए आवश्यक कोष्ठक (और कई मापदंडों के मामले में अल्पविराम) के रूप में एक खाली तर्क सूची को शामिल करने के लिए प्रतीत नहीं होता है
अनुगामी अल्पविराम की समस्या के लिए, जो कि एक अतिरिक्त पहचानकर्ता को संश्लिष्ट में जोड़कर हल किया जाता है (मेरे मामले में, MMMM जो कि पहचानकर्ता के लिए 3999 का पालन करने के लिए कुछ भी उतना ही उचित लगता है, भले ही वह रोमन अंतिम क्रम अनुक्रमण के स्वीकृत नियमों का पालन न करता हो। ठीक ठीक)।
एक छोटे से क्लीनर समाधान में एनम को हिलाना और एक अलग हेडर फाइल को सपोर्ट करना शामिल होगा जैसा कि एक टिप्पणी में कहीं और निहित था, और मैक्रो नामों के अपरिभाषित का उपयोग करने के तुरंत बाद उनका उपयोग किया गया ताकि नाम स्थान को प्रदूषित करने से बचें। बेहतर मैक्रो नामों को बेशक चुना जाना चाहिए, लेकिन यह कार्य के लिए पर्याप्त है।
मेरे मूल समाधान के बाद मेरा अद्यतन समाधान:
#define _0(i,v,x)
#define _1(i,v,x) i
#define _2(i,v,x) i##i
#define _3(i,v,x) i##i##i
#define _4(i,v,x) i##v
#define _5(i,v,x) v
#define _6(i,v,x) v##i
#define _7(i,v,x) v##i##i
#define _8(i,v,x) v##i##i##i
#define _9(i,v,x) i##x
#define k(p,s) p##s,
#define j(p,s) k(p,s)
#define i(p) j(p,_0(I,V,X)) j(p,_1(I,V,X)) j(p,_2(I,V,X)) j(p,_3(I,V,X)) j(p,_4(I,V,X)) j(p,_5(I,V,X)) j(p,_6(I,V,X)) j(p,_7(I,V,X)) j(p,_8(I,V,X)) j(p,_9(I,V,X))
#define h(p,s) i(p##s)
#define g(p,s) h(p,s)
#define f(p) g(p,_0(X,L,C)) g(p,_1(X,L,C)) g(p,_2(X,L,C)) g(p,_3(X,L,C)) g(p,_4(X,L,C)) g(p,_5(X,L,C)) g(p,_6(X,L,C)) g(p,_7(X,L,C)) g(p,_8(X,L,C)) g(p,_9(X,L,C))
#define e(p,s) f(p##s)
#define d(p,s) e(p,s)
#define c(p) d(p,_0(C,D,M)) d(p,_1(C,D,M)) d(p,_2(C,D,M)) d(p,_3(C,D,M)) d(p,_4(C,D,M)) d(p,_5(C,D,M)) d(p,_6(C,D,M)) d(p,_7(C,D,M)) d(p,_8(C,D,M)) d(p,_9(C,D,M))
#define b(p) c(p)
#define a() b(_0(M,N,O)) b(_1(M,N,O)) b(_2(M,N,O)) b(_3(M,N,O))
enum { _ a() MMMM };
#include <stdio.h>
int main(int argc, char** argv)
{
printf("%d", MMMCMXCIX * MMMCMXCIX);
return 0;
}
मूल उत्तर (जिसे पहले छह अपवोट प्राप्त हुए थे, इसलिए यदि कोई भी इसे फिर से नहीं बढ़ाता है, तो आपको यह नहीं सोचना चाहिए कि मेरे अपडेट किए गए समाधान को अपवोट मिला है):
पहले के उत्तर के रूप में एक ही भावना में, लेकिन केवल परिभाषित व्यवहार का उपयोग करके पोर्टेबल होना चाहिए (हालांकि विभिन्न वातावरण हमेशा प्रीप्रोसेसर के कुछ पहलुओं पर सहमत नहीं होते हैं)। कुछ मापदंडों को वैकल्पिक मानता है, दूसरों को अनदेखा करता है, इसे प्रीप्रोसेसरों पर काम करना चाहिए जो __VA_ARGS__
सी ++ सहित मैक्रो का समर्थन नहीं करते हैं , यह अप्रत्यक्ष मैक्रो का उपयोग करता है ताकि यह सुनिश्चित हो सके कि टोकन चिपकाने से पहले मापदंडों का विस्तार किया जाता है, और अंत में यह छोटा होता है और मुझे पढ़ना आसान लगता है हालांकि यह अभी भी मुश्किल है और शायद पढ़ने में आसान नहीं है , बस आसान है):
#define g(_,__) _, _##I, _##II, _##III, _##IV, _##V, _##VI, _##VII, _##VIII, _##IX,
#define f(_,__) g(_,)
#define e(_,__) f(_,) f(_##X,) f(_##XX,) f(_##XXX,) f(_##XL,) f(_##L,) f(_##LX,) f(_##LXX,) f(_##LXXX,) f(_##XC,)
#define d(_,__) e(_,)
#define c(_,__) d(_,) d(_##C,) d(_##CC,) d(_##CCC,) d(_##CD,) d(_##D,) d(_##DC,) d(_##DCC,) d(_##DCCC,) d(_##CM,)
#define b(_,__) c(_,)
#define a b(,) b(M,) b(MM,) b(MMM,)
enum { _ a };