2012-09-18 32 views
17

從C++ 11草案,7.5(第1段):外部「C」函數是一個單獨的類型嗎?

兩種功能類型的具有不同語言 鍵是不同的類型,即使它們是其它方面相同。

因此,我可以根據語言的聯繫做超負荷:

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); 
} 

但是,與GCC 4.7.1此示例代碼提供了錯誤信息:

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

只是爲了記錄:在C++ 03標準具有完全相同的同款同一句話,所以這不是編譯器尚未支持C++ 11功能的問題。 – Gorpik

+0

請參閱http://stackoverflow.com/a/10643935/1463922。確保調用C和C++的約定匹配。 – PiotrNycz

回答

8

這是gcc中已知的一個bug,他們記錄它不符合,因爲這個bug阻止了超級bug,「C++ 98一致性問題」。

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

檢查創建日期。

有接近尾聲了一些討論,關於引入的修復程序的實用性。所以回答你的最後一個問題是「兩」:它是錯誤已刻意保留在兼容性錯誤

具有相同問題的其他編譯器可能獨立做出錯誤,但我認爲更可能他們也知道,這是錯誤的,但希望是錯誤兼容與海灣合作委員會。

+0

Triky,因爲我真的使用指向模板函數的指針轉換爲指向'extern「C」'函數的指針。我不知道有什麼方法可以製作extern「C」模板函數,所以我認爲我會保留我的代碼,因爲它現在是... – rodrigo

+0

嗯,聽起來真氣。我想你可以用(最多)一個'extern「C」'wrapper函數來實現每個你使用的C API,前提是C-linkage函數需要一個用戶數據指針。通過將C++ - 鏈接函數指針存儲在用戶數據中並從那裏調用,可以將C++ - 鏈接函數指針走私到C-linkage函數。 「如果有疑問可以增加更多的間接性」,就是這樣。 –

+0

@Steve_Jessop:謝謝,我有這樣的想法,但是這打破了我在使用模板而不是具有虛擬功能和靜態成員func的調度器對象時所追求的零開銷目標...... _D'oh!_ – rodrigo

10

該代碼顯然是有效的。 G ++(以及其他一些編譯器)對於將鏈接集成到類型中是一種比較寬鬆的處理(說得很溫和)。

+0

+1根據OP提供的看法,這似乎是正確的,除非直到標準的某個角落增加了一個例外的說法。不管怎樣,知道詹姆斯我認爲他知道得更好,我相信他的話: ) –

+1

@Als這是一個經典的例子:將一個靜態成員函數傳遞給'pthread_create'(或'CreateThread')。根據該標準,這是非法的(因爲'pthread_create'需要'外部的「C」'和構件不能'的extern「C」'),但兩者g ++以及VC++允許它。 –

+0

謝謝。問題是我有一些恰好依賴於GCC行爲的代碼。它當然有效,但它讓我感到有點不舒服,因爲它看起來完全不可移植。我的問題是,這種懈怠是否是故意的,因此我可以認爲它是「GCC延伸」。 – 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

但在線[Coumeau C++編譯器](http://www.comeaucomputing.com/tryitout/)在沒有任何警告的情況下接受它! – rodrigo

相關問題