2015-03-12 21 views
22

मैं सी ++ में कुछ ओवरलोड किए गए जीसीसी निर्मित-इन्स को अनुकरण करने का एक तरीका ढूंढ रहा हूं। बनाया-इन इन के समान हैं:फ़ंक्शन जो केवल शाब्दिक पूर्णांक लेता है

__builtin_foo(char *a, signed int b); 
__builtin_foo(short *a, signed int b); 
__builtin_foo(long *a, signed int b); 
एक विशेष सीमा कठिन जीसीसी में कोडित साथ

: b एक शाब्दिक मान होना चाहिए, यानी आप कॉल कर सकते हैं:

__builtin_foo((char *)0, 1); 

लेकिन नहीं:

extern int val; 
__builtin_foo((char *)0, val); 

जो एक संकलक त्रुटि उत्पन्न करता है। मैंने इसे अनुकरण करने के लिए std::enable_if के साथ झुका दिया है लेकिन यह लागू करने का कोई तरीका नहीं मिल सकता है कि केवल शाब्दिक तर्क स्वीकार किए जाते हैं। क्या इसे करने का कोई तरीका है?

+0

#define ASSERT_LITERAL (एक्स) (शून्य) (x ## 98765L) - का कारण बनता है एक संकलन किसी भी गैर पूर्णांक के लिए त्रुटि शाब्दिक उदा ASSERT_LITERAL (x); असफल ASSERT_LITERAL (1); - उत्तीर्ण करना। उत्तर के रूप में जोड़ने के लिए बहुत हैकी – samgak

+3

@ सैमगाक: यह काम करने के लिए भी हैकी है। 'ASSERT_LITERAL (0) 'भी असफल हो जाएगा। –

+0

@ माइकसेमोर: मामूली विस्तार; 'x ## 010L' ठीक करता है। लेकिन मुझे 'ASSERT_LITERAL (0.0) ' – MSalters

उत्तर

15

आप प्रकार का स्थूल और जीसीसी आंतरिक __builtin_constant_p

constexpr int foo(int i) { return i; } 

#define FOO(i) do { \ 
    static_assert(__builtin_constant_p(i), "Not a constant"); \ 
    foo(i); \ 
} while (false) 

यह संकलन करने FOO(1) की अनुमति देगा, लेकिन नहीं int i = 1; FOO(i);

हालांकि, __builtin_constant_p का परिणाम अनुकूलन स्तर पर निर्भर करता का उपयोग कर इसे अनुकरण कर सकते हैं , अनुकूलन के उच्च स्तर पर const चर को स्थिरांक के रूप में माना जाता है, इसलिए यह केवल शाब्दिक स्वीकार नहीं करता है।

बेशक यदि आप निरंतर अभिव्यक्तियों को अनुमति देने के इच्छुक हैं, न केवल शाब्दिक, तो आपको केवल एक संदर्भ में वेरिएबल का उपयोग करना है जिसके लिए निरंतर अभिव्यक्ति की आवश्यकता होती है, जैसे स्थैतिक दावा या गैर- टेम्पलेट तर्क टाइप करें।

+0

यह अच्छा लगता है, मैं कोशिश करूँगा। असल में, बिल्टिन स्थिरांक भी स्वीकार कर सकते हैं, इसलिए यह सी ++ दृष्टिकोण के समान होगा, लेकिन मेरे पास उपयोग के मामले में वास्तव में महत्वपूर्ण नहीं है (यानी परीक्षण करना सी में काम करता है जैसे सी ++ अधिभारित कार्यों के rsolution)। – user3510167

+0

सिवाय इसके कि जीसीसी को मैक्रो में static_assert() पसंद नहीं है। :-( – user3510167

+0

@ user3510167: तो ऐतिहासिक फ़ॉलबैक में से एक का उपयोग करें, जैसे 'CHECKCONSTANT चार [i] का उपयोग;' – MSalters

13

आप किसी टेम्प्लेट में समारोह बदल सकती है:

template <int b> 
builtin_foo(char *a); 

कॉल वाक्य रचना तो builtin_foo<1>(whatever) होगा।

आप इस पसंद नहीं है, तो आप एक मैक्रो में टेम्पलेट लपेट सकता है:

#define m_builtin_foo(a, b) builtin_foo<(b)>((a)) 

निश्चित रूप से हो जाएगा ताकि किसी भी अभिन्न निरंतर अभिव्यक्ति सिर्फ एक शाब्दिक नहीं स्वीकार करते हैं,।

31

यहाँ एक पोर्टेबल सी ++ 11 समाधान है ताकि आपके समारोह (मैक्रो वास्तव में, खेद) केवल पूर्णांक शाब्दिक स्वीकार करता है और बजाय एक संकलन समय त्रुटि से चलाता है:

constexpr int operator "" _literal(unsigned long long i) 
{ 
    return i; 
} 

#define m_builtin_foo(integer) builtin_foo(integer ## _literal) 

उपयोगकर्ता-परिभाषित शाब्दिक केवल शाब्दिक स्वीकार (इसलिए उनका नाम)। इसलिए, यदि आप अपने मैक्रो पेस्ट को उपयोगकर्ता द्वारा परिभाषित शाब्दिक बनाते हैं, तो इसे केवल उपयोगकर्ता द्वारा परिभाषित शाब्दिक द्वारा स्वीकार किए गए अक्षरों को स्वीकार करना चाहिए।

हालांकि, यह बदसूरत है और मुझे लगता है कि त्रुटि-प्रवण हो सकता है। यकीन नहीं है कि कैसे।


@ माइकल एंडरसन ने टिप्पणियों में बताया कि m_builtin_foo(i+1) अभी भी काम करेगा। ये सही है। @ एंग्यू ने प्रतिरक्षा अंकगणित के साथ असंगत और स्पष्ट रूपांतरण जोड़ने के साथ एक रैपर में _literal के रिटर्न प्रकार को लपेटने का सुझाव दिया।उन्होंने यह भी सही था, यहाँ और अधिक पूर्ण समाधान है:

struct wrapper 
{ 
    constexpr wrapper(int n): 
     value{n} 
    {} 

    explicit constexpr operator int() const 
    { 
     return value; 
    } 

    int value; 
}; 

constexpr wrapper operator "" _literal(unsigned long long i) 
{ 
    return { int(i) }; 
} 

#define m_builtin_foo(integer) builtin_foo(int(integer ## _literal)) 
+1

को अन्य ओवरलोड के साथ भी विस्तारित किया जा सकता है। चतुर ! – Quentin

+3

वाह यह अच्छा है। – 0x499602D2

+4

'm_builtin_foo (x + 1)' के बारे में क्या? –

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