8

मैं सी में फ़ंक्शन ओवरलोडिंग को कार्यान्वित करने का प्रयास कर रहा हूं, और मैं बहुत करीब हूं। मैं सी 99 का उपयोग कर रहा हूं इसलिए सी 11 में पेश किए गए _Generic कीवर्ड मेरे लिए उपलब्ध नहीं है। मैंने कुछ कामकाजी कोड विकसित किए हैं, लेकिन जब मैं इसे संकलित करता हूं तो मुझे कुछ चेतावनियां मिलती हैं।जीसीसी का उपयोग कर सी में फ़ंक्शन ओवरलोडिंग - कंपाइलर चेतावनियां

कार्य उदाहरण:

#include <stdio.h> 

#define print(x)                  \ 
__builtin_choose_expr(__builtin_types_compatible_p(typeof(x), int ), print_int(x) , \ 
__builtin_choose_expr(__builtin_types_compatible_p(typeof(x), char[]), print_string(x), \ 
(void)0)) 


void print_int(int i) { 
    printf("int: %d\n", i); 
} 

void print_string(char* s) { 
    printf("char*: %s\n", s); 
} 

int main(int argc, char* argv[]) { 

    print(1); 
    print("this"); 

    return 0; 
} 

संकलन निम्नलिखित चेतावनी बनाता है:

gcc overload.c -o main 
overload.c: In function 'main': 
overload.c:19: warning: passing argument 1 of 'print_string' makes pointer from integer without a cast 
overload.c:20: warning: passing argument 1 of 'print_int' makes integer from pointer without a cast 

थोड़ा और डिबगिंग जानकारी के लिए, यहाँ मुख्य कार्य की तरह के बाद पूर्वप्रक्रमक अपने काम करता दिखता है:

int main(int argc, char* argv[]) { 

__builtin_choose_expr(__builtin_types_compatible_p(typeof(1), int), print_int(1) , __builtin_choose_expr(__builtin_types_compatible_p(typeof(1), char[]), print_string(1), (void)0)); 
__builtin_choose_expr(__builtin_types_compatible_p(typeof("this"), int), print_int("this") , __builtin_choose_expr(__builtin_types_compatible_p(typeof("this"), char[]), print_string("this"), (void)0)); 

return 0; 
} 

मैं संकलन चेतावनियां कैसे दूर कर सकता हूं और sti काम कोड होगा?

+0

मुझे विश्वास है कि यह 'print_string (1)' और 'print_int (" this ") 'पर कॉल है, जो चेतावनियां पैदा कर रहे हैं, लेकिन इन कॉलों का मिलान कभी नहीं होगा क्योंकि प्रकार मेल नहीं खाते हैं। – tjwrona1992

+0

'print_int (x)' या 'print_string (x) 'चुनने के बजाय, यदि आप' print_int' या' print_string' चुनते हैं और चुने गए फ़ंक्शन (पॉइंटर) को x पर लागू करते हैं? – user2357112

+0

@ user2357112, मैं ऐसा करने के बारे में कैसे जाऊं? मैं फ़ंक्शन पॉइंटर्स के साथ बहुत अच्छा नहीं हूं। – tjwrona1992

उत्तर

7

सिद्धांत रूप में, यह काम करना चाहिए:

#define print(x)                  \ 
(__builtin_choose_expr(__builtin_types_compatible_p(typeof(x), int ), print_int , \ 
__builtin_choose_expr(__builtin_types_compatible_p(typeof(x), char[]), print_string, \ 
(void)0))(x)) 

यह या तो print_int या print_string चुनता है, तो x करने के लिए चुना समारोह लागू होता है।

+1

जीसीसी 4.9 और क्लैंग 3.5 – Leandros

+0

पर काम करने की पुष्टि की गई यह अच्छी है, यह निर्दिष्ट प्रकार समर्थित नहीं होने पर एक कंपाइलर त्रुटि ट्रिगर करेगा। –

+0

हां यह काम करता है। धन्यवाद! – tjwrona1992

0

चेतावनी #define खंड में कुछ प्रकार के कास्टिंग कर द्वारा दबा दिया जा सकता है लेकिन मैं इस तरह लग रहा है शायद सबसे अच्छा है या बिल्कुल भी एक अच्छा समाधान नहीं है ...

बदलें समारोह #define में कॉल यह करने के लिए अनुभाग:

print_string((char*)x) 
print_int((int)x) 

मैं सच में आशा है कि किसी वजह से यह सिर्फ गलत लगता है, हालांकि एक बेहतर समाधान के साथ आता है, ...

+0

मैं अभी भी एक ही विचार के साथ आया हूं, हालांकि, यह आपको केवल एक अलग चेतावनी देगा: '-पॉइंटर-टू-इंट-कास्ट'। – Leandros

+0

मैंने इसे 'gcc -Wall' के साथ संकलित किया और यह चेतावनियों से छुटकारा पाता है। 'G ++ 'के साथ संकलन हालांकि कई त्रुटियों के साथ पूरी तरह विफल हो जाएगा। – tjwrona1992

+2

यह सी ++ में विफल रहता है क्योंकि जीसीसी के दस्तावेज के अनुसार, इनमें से कोई भी अंतर्निहित सी ++ में उपलब्ध नहीं है। – Leandros

2

बिल्ड-इन्स पर GNU page कहता है कि चुनी गई शाखाएं अभी भी वाक्यविन्यास त्रुटियां उत्पन्न कर सकती हैं, लेकिन मैं यह देखने में असफल रहा कि कैसे विसंगति प्रकार सिंटैक्स त्रुटियां हैं।

वैसे भी, जब आप प्रकार-निर्भर पसंद से फ़ंक्शन में तर्क लेते हैं तो आप चेतावनियों से छुटकारा पा सकते हैं। तो (क्रम में स्यूडोकोड में इसे और अधिक पठनीय बनाने के लिए),

choose_type_of(x, int, print_int(x), 
choose_type_of(x, char[], print_string(x), (void) 0)) 

के बजाय

choose_type_of(x, int, print_int, 
choose_type_of(x, char[], print_string, pass))(x) 

करते हैं यही कारण है कि एक टिप्पणी में सुझाव दिया user2357112। मैं इसी तरह के समाधान पर काम कर रहा था, लेकिन मुझे काम करने के लिए डिफ़ॉल्ट भाग (pass ऊपर) प्राप्त करने में कठिन समय था। जब मैं (void) का उपयोग करता हूं, तो उसे (void)(x) तक विस्तारित करना चाहिए, मुझे एक बेजोड़ कोष्ठक के बारे में त्रुटि मिलती है।

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

#include <stdio.h> 

#define print(x)             \ 
    __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), \ 
     int), print_int,           \ 
    __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), \ 
     const char[]), print_string,        \ 
    print_any))(x) 


void print_int(int i) { 
    printf("int: %d\n", i); 
} 

void print_string(const char *s) { 
    printf("char[]: %s\n", s); 
} 

void print_any() { 
    printf("unknown\n"); 
} 

int main(void) 
{ 
    int n = 9; 
    const char str[] = "hello"; 

    print(n); 
    print(str); 

    print(1); 
    print("this"); 

    print(3.2); 

    return 0; 
} 
+0

'(शून्य) 'काम नहीं किया क्योंकि हम एक अभिव्यक्ति चुन रहे हैं, टोकन का अनुक्रम नहीं, और' (शून्य) 'पूरी अभिव्यक्ति नहीं है। – user2357112

+0

@ उपयोगकर्ता 2357112: अच्छा बिंदु। डिफ़ॉल्ट खंड में एक कंपाइलर त्रुटि उत्पन्न करना शायद वैसे भी बेहतर दृष्टिकोण है। –

1

फ़ंक्शन ओवरलोडिंग प्राप्त करने वाली कई विधियों के साथ यहां एक उदाहरण दिया गया है।

एक पोस्टर का निर्माण-इन पर इस

जीएनयू पेज का कहना है कि शाखाओं सकता है अभी भी सिंटैक्स त्रुटि उत्पन्न नहीं चुना उल्लेख किया है, लेकिन मैं कैसे बेमेल प्रकार वाक्यविन्यास त्रुटियों को देखने के लिए असफल।

वाक्यविन्यास त्रुटियों वे की बात कर रहे हैं मेरा मानना ​​है कि संकलक चेतावनी आप क्योंकि संकलक preprocessing देख सकते हैं कि कुछ कार्यों के लिए तर्क के प्रकार, भले ही वे कभी नहीं कहा जा सकता है गलत हैं के बाद प्राप्त कर रहे हैं। समाधान (जो मुझे लगता है कि काफी साफ है) कंपाइलर से प्रकार छिपाने का एक तरीका ढूंढना है। स्पष्ट तरीका varargs है, कम स्पष्ट तरीका ओपी के सवाल का वर्तमान जवाब है।

चेतावनियां यानी लागू नहीं सब समाधान प्रकार सुरक्षित हैं और यह पूरी तरह जीएनयू के लिए विशिष्ट है ...

#include <stdarg.h> 
#include <stdlib.h> 
#include <stdio.h> 

#define print(x)                  \ 
    (__builtin_choose_expr(__builtin_types_compatible_p(typeof(x), int ), print_int , \ 
    __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), char[]), print_string, \ 
    (void)0))(x)) 

#define print1(x)                   \ 
    __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), int ), print_int1(1,x) , \ 
    __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), char[]), print_string1(1,x), \ 
(void)0)) 

#define print2(x)                 \ 
    __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), int ), printer(1,x), \ 
    __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), char[]), printer(2,x), \ 
(void)0)) 

#define TYPE_ID(x) __builtin_types_compatible_p(typeof(x), int ) * 1 \ 
       + __builtin_types_compatible_p(typeof(x), char[]) * 2 

#define print3(x) printer(TYPE_ID(x), x) 

#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1] 

#define print4(x) \ 
    STATIC_ASSERT(TYPE_ID(x), __LINE__); \ 
    printer(TYPE_ID(x), x) 

void printer(int i, ...) { 
    va_list v; 
    va_start(v, i); 
    switch(i) { 
    case 1:{ 
      int arg = va_arg(v, int); 
      printf("int: %d\n", arg); 
      va_end(v); 
      break; 
      } 
    case 2:{ 
      char * arg = va_arg(v, char*); 
      printf("char*: %s\n", arg); 
      va_end(v); 
      break; 
      } 
    default: { 
       fprintf(stderr, "Unknown type, abort\n"); 
       abort(); 
      } 
    } 
} 

void print_int(int i) { 
    printf("int: %d\n", i); 
} 

void print_string(char* s) { 
    printf("char*: %s\n", s); 
} 
void print_int1(int i, ...) { 
    va_list v; 
    va_start(v, i); 
    int arg = va_arg(v, int); 
    printf("int: %d\n", arg); 
    va_end(v); 
} 

void print_string1(int i, ...) { 
    va_list v; 
    va_start(v, i); 
    char * arg = va_arg(v, char*); 
    printf("char*: %s\n", arg); 
    va_end(v); 
} 
int main(int argc, char* argv[]) { 
    int var = 1729; 
    double var1 = 1729; 
    //Type safe 
    //print(var1);//Comple time error 
    print(var); 
    print("print"); 

    /* Following are not Type Safe */ 
    print1(var1);// BAD... Does nothing. 
    print1(var); 
    print1("print1"); 

    print2(var1);// BAD... Does nothing. 
    print2(var); 
    print2("print2"); 

    //print3(var1);//Evil... Runtime error 
    print3(var); 
    print3("print3"); 

    //Type Safe 
    //print4(var1);//Comple time error 
    print4(var); 
    print4("print4"); 
    return 0; 
} 

स्रोत GitHub पर है ...

https://github.com/harryjackson/doc/blob/master/c/overload_c_functions.c

के साथ स्विच विधि कई तर्क यहां पाए जा सकते हैं ...

http://locklessinc.com/articles/overloading/

संपूर्ण

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