2012-09-18 27 views
17

od C++ 11 roboczej, 7,5 (p. 1):Czy zewnętrzne funkcje "C" są osobnym rodzajem?

dwa typy funkcyjnych z innym języku wiązania są różne typy, nawet jeśli nie są inaczej identyczne.

Więc mogę zrobić przeciążenie na podstawie powiązań językowych:

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

Ale z GCC 4.7.1 ten przykładowy kod daje komunikaty o błędach:

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 

iz brzękiem ++

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) 
    ^

Teraz pytania:

  • Czy moje zrozumienie normy jest prawidłowe? Czy ten kod jest prawidłowy?

  • Czy ktoś wie, czy są to błędy w kompilatorach, czy też celowo robią to w ten sposób dla celów zgodności?

+0

Tak dla przypomnienia: standard C++ 03 ma dokładnie to samo zdanie w tym samym punkcie, więc ta nie jest kwestią funkcji C++ 11, która nie jest jeszcze obsługiwana przez kompilatory. – Gorpik

+0

Zobacz http://stackoverflow.com/a/10643935/1463922. Upewnij się, że konwencje wywoływania C i C++ są zgodne. – PiotrNycz

Odpowiedz

8

To znany błąd w gcc i rejestrują, że jest niezgodny, ponieważ błąd ten blokuje uber-bug, "problemy ze zgodnością z C++ 98".

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

Sprawdź datę utworzenia.

Pod koniec dyskusji, na temat praktycznych aspektów wprowadzenia poprawki. Tak więc odpowiedź na ostatnie pytanie brzmi "oba": jest to błąd i błąd został celowo pozostawiony w celu zapewnienia zgodności.

Inne kompilatory z tym samym problemem mogły utworzyć błąd niezależnie, ale wydaje mi się, że najprawdopodobniej wiedzą również, że są błędne, ale chcą być kompatybilne z gcc.

+0

Triky, ponieważ tak naprawdę używam wskaźników do funkcji szablonowych przekonwertowanych na wskaźniki do funkcji "extern" C "'. Nie wiem, w jaki sposób utworzyć funkcję szablonu "extern" C ", więc myślę, że zachowam mój kod jak na razie ... – rodrigo

+0

Mmm, brzmi to irytująco. Domyślam się, że możesz to zrobić z (co najwyżej) jedną 'zewnętrzną 'funkcją" C "' na API C, którego używasz, pod warunkiem, że funkcja C-link pobiera wskaźnik danych użytkownika. Przeszukujesz wskaźnik funkcji powiązania C++ z funkcją C-linkage, zapisując ją w danych użytkownika i wywołując ją stamtąd. "Jeśli masz wątpliwości, dodaj więcej pośrednictwa", coś w tym stylu. –

+0

@Steve_Jessop: Dzięki, miałem coś takiego na myśli, ale to niszczy mój cel, który był zerowy, który realizowałem przy użyciu szablonów zamiast obiektu dyspozytora z funkcją wirtualną i funkcją statycznego członka ... _D'oh! _ – rodrigo

10

Kod jest wyraźnie ważny. G ++ (i pewna liczba innych kompilatorów) to luna (delikatnie mówiąc) o integracji tego typu z typem.

+0

+1 Na podstawie tego, co OP podało, wydaje się to poprawne, chyba że jest jakiś zakątek normy, który dodaje wyjątek do wspomnianego cytatu. W każdym razie, Znając Jamesa, myślę, że on wie lepiej i ufam jego słowu na ten temat:) –

+1

@Als Klasyczny przykład, w którym to robi różnicę: przekazywanie statycznej funkcji składowej do 'pthread_create' (lub' CreateThread'). Zgodnie ze standardem jest to nielegalne (ponieważ 'pthread_create' wymaga' extern 'C "', a element nie może być 'extern" C "'), ale pozwalają na to zarówno g ++, jak i VC++. –

+0

Dzięki. Chodzi o to, że mam trochę kodu, który zdaje się polegać na tym zachowaniu GCC.Działa to oczywiście, ale sprawia, że ​​czuję się trochę niekomfortowo, ponieważ wydaje się całkowicie nieprzenośny. Moim problemem jest to, czy ta rozluźnienie jest zamierzona, i dlatego mogę uznać to za "rozszerzenie GCC". – rodrigo

1

Na co warto, ten kod nie powiedzie się także skompilować z ustawieniami domyślnymi w 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

Ale internetowy [kompilator Coumeau C++] (http://www.comeaucomputing.com/tryitout/) akceptuje go bez żadnego ostrzeżenia! – rodrigo