web-dev-qa-db-de.com

fehler bei der dynamischen Ausnahmebedingung für C++ 1z

Ich versuche, mein Projekt mit der neuen GCC-Version 7.2.1 zu kompilieren und habe ein Problem mit den dynamischen Ausnahmespezifikationen:

error: ISO C++1z does not allow dynamic exception specifications
  MEMORY_ALLOC_OPERATORS(SQLException)

Das Problem ist, dass diese Fehler aus Bibliotheken von Drittanbietern stammen, die ich nicht kontrolliere.

Gibt es eine Möglichkeit, das Problem zu beheben? Soweit ich weiß, kann ich dem Compiler nicht mitteilen, dass er Fehler durch Warnungen ersetzen soll. Die Verwendung von --std=c++14 ist keine Option, da ich neue Funktionen von C++ 1z verwenden möchte.

8

C++ 17 hat dynamische Ausnahmespezifikationen aufgrund von P0003 entfernt. Zuvor waren sie seit C++ 11 veraltet. Sie sind nicht mehr Teil der Sprache, daher gibt es keine Möglichkeit, sie zu korrigieren. Solange Sie diese Drittanbieter-Bibliothek benötigen, bleiben Sie bei C++ 14, bis sie sich ändert.


Wenn Sie verzweifelt sind, können Sie Folgendes versuchen:

#define throw(...)

aber ich würde es nicht empfehlen. 

7
Barry

Nun, ich habe eine kleine Abhilfe geschrieben.

#if __cplusplus >= 201703L
    /* MySQL override. This needed to be inclided before cppconn/exception.h to define them */
    #include <stdexcept>
        #include <string>
    #include <memory>

    /* Now remove the trow */
    #define throw(...)
    #include <cppconn/exception.h>
    #undef throw /* reset */
#endif

Kurze Erklärung: Wenn wir c ++ 17 verwenden, ist das Werfen auf Zuordnern nicht mehr zulässig. Wenn Sie sich die Kopfzeile der Bibliothek genauer ansehen, werden Sie feststellen, dass dies vorhanden ist ein definiertes Makro, das die Definitionen für den Standardzuweiser in der Bibliothek enthält. Leider kann es nicht überschrieben werden, da es dort definiert wird und ignoriert, was bereits definiert ist. Also muss man die Trow irgendwie ohnehin überschreiben.

Ein grundlegender Trick besteht darin, die Trow-Funktion mit einem Makro zu überschreiben. Dies führt uns zu dem Problem, dass wir auch den Trow-Operator für alle Include-Elemente in der Bibliothek überschreiben, was keine gute Lösung ist (und auch nicht funktioniert). Wie Sie vielleicht wissen Wenn Sie einen Header hinzufügen, wird dieser nur einmal eingefügt (meistens dank der Header-Wachen). Der Trick besteht also darin, die Header, die in der Bibliothek enthalten sind, einzuschließen throw include den Header der Zielbibliothek, die ihren Header nicht wieder enthält, da wir dies bereits getan haben. 

3
WolverinDEV
  1. Isolationsschicht wie oben erwähnt. So etwas wie:

#if __cplusplus < 201703L // Standards below C++2017

 void fn() throw (int) { }

#endif // __cplusplus

  1. Es ist höchste Zeit, throw(whatever) durch noexcept(false) zu ersetzen.

Seien Sie auf jeden Fall bereit für etwas Spaß!

1
ibroheem

Ich habe das gleiche Problem gemacht, also musste ich diese Makrodefinition in /usr/include/cppconn/exception.h ändern:

#define MEMORY_ALLOC_OPERATORS(Class) \
void* operator new(size_t size) noexcept(false) { return ::operator new(size); }  \
void* operator new(size_t, void*) noexcept; \
void* operator new(size_t, const std::nothrow_t&) noexcept; \
void* operator new[](size_t) noexcept(false); \
void* operator new[](size_t, void*) noexcept; \
void* operator new[](size_t, const std::nothrow_t&) noexcept; \
void* operator new(size_t N, std::allocator<Class>&);
1
cocheci

In MSVC war Ihr Wurfspezifizierer (...) ohnehin immer ein Leerraum. Wie in Visual Studio wurde eine Funktion wie folgt im Hintergrund kompiliert:

void SomeFunction() throw(std::string) {...} 

WENN es war:

void SomeFunction() {...}

oder in modernen C++ 11 ab:

void SomeFunction() noexcept(false) {...}

Für 99% aller plattformübergreifenden 3P-Pakete konzentrieren sich das Makro und die # include-Hacks auf:

#define throw(...) 

werden sofort funktionieren, da die systemeigenen Windows-Builds des Pakets bereits im Hintergrund ausführen, was dieses Makro bewirkt. Andernfalls können Sie alle Aufrufe und Verweise auf die fehlerhaften Schnittstellen in einige eigene C++ 14-Quelldateien einbinden. Damit kann zumindest der Rest Ihres Projekts C++ 17 verwenden.

0
user3726672