2014-06-23 9 views
20

Nie mogę znaleźć niczego w standardzie, który wymusza funkcje zadeklarowane przy extern "C" jako noexcept, niejawnie lub jawnie.Czy standard C++ nakazuje, aby funkcje C-łącznika były "nie tylko"?

Jednak powinno być jasne, że konwencje wywoływania C nie obsługują wyjątków ... czy jest?

Czy wzmianka o tym istnieje, gdzieś, że tęskniłem? Jeśli nie, dlaczego nie? Czy jest to po prostu rodzaj szczegółowości wdrożenia?

+0

nie wyobrażam sobie tej skali przerwy zgodności w ewolucji języka C++, czyż nie? – Sheen

+2

To jest dość wątpliwe, czy złamie kompatybilność. Programy, które wyciekają wyjątki z funkcji C, zawsze mogły mieć niezdefiniowane zachowanie. – Puppy

+4

Powiązane http://stackoverflow.com/a/15845731/242520 –

Odpowiedz

17

O ile mogę powiedzieć, nie ma gwarancji, że funkcja zdefiniowana za pomocą linku "C" nie spowoduje wyjątków. Standard umożliwia programowi C++ zarówno wywoływanie funkcji zewnętrznej z łączem języka "C", jak i definiowanie funkcji napisanych w języku C++, które mają połączenie języka "C". Dlatego nic nie stoi na przeszkodzie, aby program w C++ wywoływał funkcję z łączeniem językowym "C", które faktycznie jest napisane w C++ (w innej jednostce kompilacji może, chociaż nawet to nie jest konieczne). Byłoby to dziwne, ale trudno to wykluczyć. Również nie widzę gdzie w standardzie mówi, że spowodowałoby to niezdefiniowane zachowanie (w rzeczywistości, ponieważ Standard nie może zdefiniować funkcji nie zapisanej w C++, byłoby to użycie tylko wtedy, gdy formalnie nie ma niezdefiniowane zachowanie).

W konsekwencji myślę, że błędem byłoby zakładać, że powiązanie "C" implikuje noexcept.

+1

Dobra odpowiedź, na pewno wiesz, jak poprawnie wymawiać słowa. – didierc

+2

Mniej dziwna sytuacja byłaby funkcją C, która akceptuje (i wywołuje) wskaźnik funkcji, który może wskazywać na funkcję C++, która wyrzuca. –

8

Um, przypuszczam, że extern "C" wystarczy użyć funkcji C-link, a nie funkcji C. Zapobiega wykonywaniu kompilatora C++ name mangling.

Bardziej bezpośrednio - załóż ten kod.

// foo.cpp 
extern "C" void foo() 
{ 
    throw 1; 
} 

// bar.cpp 
extern "C" void foo(); 
void bar() 
{ 
    try 
    { 
     foo(); 
    } 
    catch (int) 
    { 
     // yeah! 
    } 
} 
+1

W rzeczywistości jest o wiele więcej niż samo zapobieganie wymieszaniu nazw. 'extern" C++ "void Foo();' różni się od 'extern 'C" void Foo(); '. Są to różne ** typy ** i mają różne właściwości, z których powiązanie jest tylko jednym z nich. –

+1

Myślałem, że wpłynie to również na konwencję wywoływania, a te wyjątki wymagały szczególnej konwencji wywoływania dla rozwijania stosów do pracy. –