2015-08-27 4 views
5

जैसा कि प्रतीत होता है, सी ++ प्रीप्रोसेसर विफल रहता है यदि एक तर्क के रूप में एक मैक्रो को एकाधिक तर्कों के साथ एक टेम्पलेट त्वरण पारित किया जाता है।सी ++ प्रीप्रोसेसर टेम्पलेट तर्कों से अवगत नहीं हैं?

नीचे एक उदाहरण देखें।

#include <stdio.h> 

#define FOO(v) printf("%d\n",v::val()) 

template<int N> 
struct bar { 
    static int val() { return N; } 
}; 
template<int N, int M> 
struct baz { 
    static int val() { return N+M; } 
}; 

int main() { 
    printf("%d\n",bar<1>::val()); 
    printf("%d\n",baz<1,2>::val()); 
    FOO(bar<10>);  // OK 
    FOO(baz<20,30>); // error: too many arguments provided to function-like macro invocation 
    FOO((baz<20,30>)); // error: '::val' has not been declared 
} 

साथ Tested बजना ++ और जी ++

यह एक बग के रूप में माना जाना चाहिए?

+1

आप मैक्रो एक parenthesized तर्क के अंदर निकालने के लिए डिजाइन सकता है, लेकिन इस उदाहरण निश्चित रूप से एक मैक्रो जरूरत नहीं है। – chris

+0

एक संबंधित प्रश्न: क्या सी ++ प्रीप्रोसेसर सी ++ के बारे में जानते हैं? AFCICT सी ++ प्रीप्रोसेसर में बहुत कुछ नहीं बदला है क्योंकि यह केवल सी प्रीप्रोसेसर था ...;) –

+1

@ क्रिस, धन्यवाद, आपके संदेश से शब्द के साथ मुझे एक समान प्रश्न का उत्तर मिला http://stackoverflow.com/प्रश्न/13842468/कॉमा-इन-सीसी-मैक्रो/13842784 # 13842784 – hutorny

उत्तर

2

सी/सी ++ प्रीप्रोसेसर कॉमा को मैक्रो तर्क विभाजक के रूप में मान्यता देता है जब तक कि वे कोष्ठक के अंदर घोंसले न हों। बस कोष्ठक। कोष्ठक, ब्रेसिज़ और टेम्पलेट मार्करों गिनती नहीं है:

सूची में अलग-अलग तर्क अल्पविराम preprocessing टोकन से अलग कर दिया जाता है, लेकिन मिलान भीतरी कोष्ठकों के बीच अल्पविराम preprocessing टोकन अलग तर्क नहीं है। (सी ++ 14 § 16.3/11; C11 § 6.10.3/11)

(ऊपर का एक पक्ष प्रभाव है कि आप मैक्रो तर्कों के रूप असंतुलित ब्रेसिज़ और कोष्ठक का उपयोग कर सकते है यही कारण है कि आम तौर पर एक बहुत अच्छा नहीं है। विचार, लेकिन अगर आपको करना है तो आप इसे कर सकते हैं।)

समस्याएं कभी-कभी परिणामस्वरूप फसल हो जाती हैं; ,

MY_FANCY_MACRO(1000, { int i=0, j=42; ... }) 

यहाँ, मैक्रो के साथ (कम से कम) 3 तर्क कहा जाता है, हालांकि यह शायद 2.

स्वीकार करने के लिए लिखा गया था: एक आम एक जब तर्क कोड का एक खंड माना जाता है अवांछित कई तर्क है

आधुनिक सी ++ (और सी) कंपाइलर्स के साथ, आपके पास कुछ विकल्प हैं। एक काफी व्यक्तिपरक क्रम में:

  1. मैक्रो को एक इनलाइन फ़ंक्शन के रूप में लिखें। यदि तर्क एक कोड ब्लॉक है, तो एक टेम्पलेटेड फ़ंक्शन का उपयोग करने पर विचार करें जो लैम्ब्डा या अन्य मज़ेदार को स्वीकार कर सकता है। यदि तर्क एक प्रकार है, तो इसे इसके बजाय टेम्पलेट तर्क बनाएं।

  2. यदि अनावश्यक कोष्ठक के साथ तर्क के आस-पास तर्कसंगत रूप से मान्य है, तो ऐसा करें। लेकिन इस तरह के मामले में यह लगभग निश्चित रूप से मामला है कि उपरोक्त सुझाव (1) काम करेगा।

  3. परिभाषित करें:

    #define COMMA , 
    

    और इसका इस्तेमाल करते हैं जहां आवश्यक:

    FOO(baz<20 COMMA 30>); 
    

    यह किसी भी तरह से मैक्रो परिभाषा को संशोधित करने की आवश्यकता नहीं है, लेकिन मैक्रो तर्क गुजरता है अगर यह असफल हो जायेगी एक और मैक्रो के लिए। (आंतरिक मैक्रो कॉल को पारदर्शी करने से पहले प्रतिस्थापन किया जाएगा, इसलिए एकाधिक तर्क समस्या को केवल आंतरिक कॉल में स्थगित कर दिया जाएगा।)

  4. यदि आप उम्मीद करते हैं कि एक मैक्रो तर्क में असुरक्षित अल्पविराम हो सकते हैं, और यह है अंतिम या केवल तर्क, और आप मैक्रो को संशोधित करने की स्थिति में हैं, और आप सी ++ 11/सी 99 या बेहतर (या जीसीसी, जिसने इसे कुछ समय के लिए विस्तार के रूप में अनुमति दी है) का उपयोग कर रहे हैं, मैक्रो वैरिएडिक बनाएं :

    #define FOO(...) printf("%d\n",__VA_ARGS__::val()) 
    
11

नहीं, यह एक बग नहीं है।

सी प्रीप्रोसेसर शेष भाषा से एक अलग जानवर है और यह अपने नियमों से चलता है। इसे बदलने से बड़े पैमाने पर संगतता टूट जाएगी, सीपीपी अत्यधिक कठोर मानकीकृत है।

सामान्य इन अल्पविराम मुद्दों को हल करने के लिए जिस तरह से, है

typedef baz<20,30> baz2030_type; 
FOO(baz2030_type); 
1

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

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