问题
I am trying to compile my project with new GCC version 7.2.1 and have a problem with dynamic exception specifications:
error: ISO C++1z does not allow dynamic exception specifications
MEMORY_ALLOC_OPERATORS(SQLException)
The problem is that these errors come from third-party libraries which I do not control.
Is there a some way to fix it? As far as I know I can't tell compiler to replace errors with warnings. Using --std=c++14
is not an option because I want to use new features from C++1z.
回答1:
C++17 removed dynamic exception specifications, as a result of P0003. Before that, they had been deprecated since C++11. They are no longer part of the language, so there isn't really a way to fix it. As long as you need that third party library, until it changes, you're stuck on C++14.
If you're desperate, you could try:
#define throw(...)
but I wouldn't recommend it.
回答2:
Well i wrote a little workaround.
#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
Short explanation: If we're using c++17, throw is not allowed anymore on allocators. If you take a closer look at the header of the library you'll see that there is a macro defined, which contains the definitions for the default allocator within the library. Sadly it can't be overridden because it gets defined there ignoring that's may already be defined. So somehow you have to override the trow anyway.
A basic trick is to override the trow function with a macro. Doing that leads us to the problem that we also override the trow operator for all includes within the library which isn't a good solution (and also doesn't work). As you may know, if you're includeing a header, it will be just included once (mostly, thanks to the header guards). So the trick there is to include the headers, which are included by the library, than override the throw include the header of the target library, which doesn't actually include their header again because we already did.
回答3:
Ran into the same issue, so I had to change this macro definition in /usr/include/cppconn/exception.h:
#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>&);
回答4:
- Isolation Layer as mentioned as mentioned in comment above. Something like:
#if __cplusplus < 201703L // Standards below C++2017
void fn() throw (int) { }
#endif // __cplusplus
- It's high time u started replacing
throw(whatever)
withnoexcept(false)
.
Either way, be ready for some fun!
回答5:
In MSVC your throw(...) specifier has always been effectively white space anyway. As in, Visual Studio has always silently compiled a function like:
void SomeFunction() throw(std::string) {...}
AS IF it was:
void SomeFunction() {...}
or in modern C++11 onward:
void SomeFunction() noexcept(false) {...}
So, for 99% of all cross-platform 3P packages the macro and #include hacks centering on:
#define throw(...)
are going to work immediately because the package's native Windows builds are already silently doing what that macro does. Failing that, you can wrap all calls & references to the offending interfaces in a couple of C++14 source files of your own. That'll at least let the rest of your project use c++17.
来源:https://stackoverflow.com/questions/47284705/c1z-dynamic-exception-specification-error