2012-09-18 20 views
17

सी ++ 11 मसौदा, 7.5 (पैरा 1।) से:क्या बाहरी "सी" एक अलग प्रकार का कार्य करता है?

दो अलग अलग भाषा के साथ समारोह प्रकार लिंकेज भिन्न प्रकार भले ही वे अन्यथा समान हैं कर रहे हैं। जीसीसी 4.7.1 के साथ इस नमूना कोड त्रुटि संदेश देता है

extern "C" typedef void (*c_function)(); 
typedef void (*cpp_function)(); 

void call_fun(c_function f) 
{ 
} 
void call_fun(cpp_function f) 
{ 
} 

extern "C" void my_c() 
{ 
} 
void my_cpp() 
{ 
} 
int main() 
{ 
    call_fun(my_c); 
    call_fun(my_cpp); 
} 

लेकिन,:

test.cpp: In function 'void call_fun(cpp_function)': 
test.cpp:7:6: error: redefinition of 'void call_fun(cpp_function)' 
test.cpp:4:6: error: 'void call_fun(c_function)' previously defined here 

और बजना साथ ++:

तो मैं अधिभार भाषा संबंधों के आधार पर कर सकते हैं

test.cpp:7:6: error: redefinition of 'call_fun' 
void call_fun(cpp_function f) 
    ^
test.cpp:4:6: note: previous definition is here 
void call_fun(c_function f) 
    ^

अब प्रश्न:

  • क्या मानक सही मेरी समझ है? क्या यह कोड मान्य है?

  • क्या किसी को पता है कि ये कंपाइलर्स में बग हैं या यदि वे जानबूझकर अनुकूलता उद्देश्यों के लिए ऐसा कर रहे हैं?

+0

: सी ++ 03 मानक एक ही पैराग्राफ में बिल्कुल एक ही वाक्य है, तो इस एक C++ 11 सुविधा का सवाल नहीं है जो अभी तक कंपाइलर्स द्वारा समर्थित नहीं है। – Gorpik

+0

http://stackoverflow.com/a/10643935/1463922 देखें। सुनिश्चित करें कि सी और सी ++ मैच के कॉलिंग सम्मेलन। – PiotrNycz

उत्तर

8

यह जीसीसी में एक ज्ञात बग है, और वे रिकॉर्ड करते हैं कि यह गैर-अनुरूप है क्योंकि यह बग उबर-बग, "सी ++ 98 अनुरूपता मुद्दों" को अवरुद्ध करता है।

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316

चेक निर्माण तिथि।

एक फिक्स पेश करने की व्यावहारिकताओं के बारे में अंत में कुछ चर्चा है। तो आपके अंतिम प्रश्न का उत्तर "दोनों" है: यह एक बग और बग को जानबूझकर संगतता के लिए छोड़ दिया गया है।

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

+0

ट्राकी, क्योंकि मैं वास्तव में पॉइंटर्स को 'बाहरी' सी '' कार्यों में परिवर्तित टेम्पलेट फ़ंक्शंस के पॉइंटर्स का उपयोग कर रहा हूं। मुझे 'बाहरी "सी' टेम्पलेट फ़ंक्शन बनाने के किसी भी तरीके से नहीं पता है, इसलिए मुझे लगता है कि मैं अपना कोड तब तक रखूंगा जैसा कि यह अभी है ... – rodrigo

+0

एमएम, क्रूर लगता है। मुझे लगता है कि आप इसका उपयोग कर सकते हैं (सबसे अधिक) एक 'बाहरी "सी" 'प्रति सीपी एपीआई जो आपके द्वारा उपयोग किया जाता है, बशर्ते कि सी-लिंकेज फ़ंक्शन उपयोगकर्ता डेटा पॉइंटर लेता है। आप अपने सी ++ - लिंकेज फ़ंक्शन पॉइंटर को सी-लिंकेज फ़ंक्शन में उपयोगकर्ता डेटा में संग्रहीत करके उसे वहां से कॉल करते हैं। "अगर संदेह में अधिक संकेत जोड़ें", चीज की तरह। –

+0

@Steve_Jessop: धन्यवाद, मेरे मन में ऐसा कुछ था, लेकिन यह मेरे शून्य-ओवरहेड उद्देश्य को तोड़ देता है जिसे मैंने वर्चुअल फ़ंक्शन और एक स्थिर सदस्य func के साथ प्रेषक ऑब्जेक्ट के बजाय टेम्पलेट का उपयोग करते समय पीछा किया ... _D'oh! _ – rodrigo

10

कोड स्पष्ट रूप से मान्य है। जी ++ (और कई अन्य कंपाइलर्स) बिट लक्स (इसे हल्के ढंग से रखने के लिए) प्रकार में लिंक को एकीकृत करने के बारे में हैं।

+0

+1 जो ओपी प्रदान किया गया उद्धरण के आधार पर यह सही प्रतीत होता है, जब तक कि मानक के कुछ कोने न हों, जो कहा गया उद्धरण के लिए अपवाद जोड़ता है। किसी भी तरह, जेम्स को जानना मुझे लगता है कि वह बेहतर जानता है और मैं उस पर अपने शब्द पर भरोसा करता हूं:) –

+1

@Als शास्त्रीय उदाहरण जहां यह एक फर्क पड़ता है: एक स्थिर सदस्य फ़ंक्शन को 'pthread_create' (या' CreateThread') में पास करना। मानक के मुताबिक, यह अवैध है (चूंकि 'pthread_create' को' बाहरी 'सी' 'की आवश्यकता होती है, और कोई सदस्य' बाहरी 'नहीं हो सकता है, लेकिन दोनों g ++ और VC++ इसे अनुमति देते हैं। –

+0

धन्यवाद। बात यह है कि मेरे पास कुछ कोड है जो इस जीसीसी व्यवहार पर भरोसा करता है।यह निश्चित रूप से काम करता है, लेकिन यह मुझे थोड़ा असहज बनाता है क्योंकि यह पूरी तरह से गैर पोर्टेबल लगता है। मेरा मुद्दा यह है कि क्या यह अक्षांश जानबूझकर है, और इस प्रकार मैं इसे "जीसीसी विस्तार" मान सकता हूं। – rodrigo

1

क्या इसके लायक है के लिए, यह कोड भी VS2012 में डिफ़ॉल्ट सेटिंग्स के साथ संकलित करने के लिए विफल रहता है:

(8) error C2084: function 'void call_fun(c_function)' already has a body 
(4) see previous definition of 'call_fun' 
(19) error C3861: 'call_fun': identifier not found 
(20) error C3861: 'call_fun': identifier not found 
बस रिकार्ड के लिए
+0

लेकिन ऑनलाइन [क्यूमेउ सी ++ कंपाइलर] (http://www.comeaucomputing.com/tryitout/) बिना किसी चेतावनी के इसे स्वीकार करता है! – rodrigo

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