c++1z 动态异常规范错误
c++1z dynamic exception specification error
我正在尝试使用新的 GCC 版本 7.2.1 编译我的项目,但遇到动态异常规范问题:
error: ISO C++1z does not allow dynamic exception specifications
MEMORY_ALLOC_OPERATORS(SQLException)
问题是这些错误来自我无法控制的第三方库。
有什么办法可以解决吗?据我所知,我不能告诉编译器用警告替换错误。使用 --std=c++14
不是一个选项,因为我想使用 C++1z 的新功能。
C++17 删除了动态异常规范,作为 P0003 的结果。在此之前,它们从 C++11 开始就被弃用了。它们不再是语言的一部分,所以没有办法修复它。只要你需要那个第三方库,直到它发生变化,你就会被困在 C++14 上。
如果你迫不及待了,你可以试试:
#define throw(...)
但我不推荐它。
- 如上面评论中所述的隔离层。类似于:
#if __cplusplus < 201703L // Standards below C++2017
void fn() throw (int) { }
#endif // __cplusplus
- 是时候开始用
noexcept(false)
替换 throw(whatever)
了。
无论如何,准备好享受一些乐趣吧!
运行 进入同样的问题,所以我不得不在 /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>&);
好吧,我写了一些解决方法。
#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
简短说明:
如果我们使用的是 c++17,则分配器上不再允许抛出。
如果仔细查看库的 header,您会发现定义了一个宏,其中包含库中默认分配器的定义。可悲的是,它不能被覆盖,因为它在那里被定义而忽略了可能已经定义的。所以无论如何你都必须覆盖 trow。
一个基本技巧是用宏覆盖 trow 函数。
这样做会导致我们还覆盖库中所有包含的 trow 运算符的问题,这不是一个好的解决方案(而且也不起作用)。
您可能知道,如果您包含 header,它将只包含一次(主要是感谢 header 守卫)。
所以这里的技巧是包含库包含的 headers,而不是覆盖目标库的 header,而实际上并不包含它们的 header再次是因为我们已经这样做了。
无论如何,在 MSVC 中,您的 throw(...) 说明符始终是有效的白色 space。例如,Visual Studio 总是默默地编译一个像这样的函数:
void SomeFunction() throw(std::string) {...}
好像是:
void SomeFunction() {...}
或在现代 C++11 之后:
void SomeFunction() noexcept(false) {...}
因此,对于 99% 的跨平台 3P 包,宏和 #include hacks 集中在:
#define throw(...)
将立即运行,因为包的本机 Windows 构建已经在默默地执行该宏所做的事情。如果做不到这一点,您可以将所有调用和对有问题的接口的引用包装在您自己的几个 C++14 源文件中。这至少会让你的项目的其余部分使用 c++17。
我正在尝试使用新的 GCC 版本 7.2.1 编译我的项目,但遇到动态异常规范问题:
error: ISO C++1z does not allow dynamic exception specifications
MEMORY_ALLOC_OPERATORS(SQLException)
问题是这些错误来自我无法控制的第三方库。
有什么办法可以解决吗?据我所知,我不能告诉编译器用警告替换错误。使用 --std=c++14
不是一个选项,因为我想使用 C++1z 的新功能。
C++17 删除了动态异常规范,作为 P0003 的结果。在此之前,它们从 C++11 开始就被弃用了。它们不再是语言的一部分,所以没有办法修复它。只要你需要那个第三方库,直到它发生变化,你就会被困在 C++14 上。
如果你迫不及待了,你可以试试:
#define throw(...)
但我不推荐它。
- 如上面评论中所述的隔离层。类似于:
#if __cplusplus < 201703L // Standards below C++2017
void fn() throw (int) { }
#endif // __cplusplus
- 是时候开始用
noexcept(false)
替换throw(whatever)
了。
无论如何,准备好享受一些乐趣吧!
运行 进入同样的问题,所以我不得不在 /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>&);
好吧,我写了一些解决方法。
#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
简短说明: 如果我们使用的是 c++17,则分配器上不再允许抛出。 如果仔细查看库的 header,您会发现定义了一个宏,其中包含库中默认分配器的定义。可悲的是,它不能被覆盖,因为它在那里被定义而忽略了可能已经定义的。所以无论如何你都必须覆盖 trow。
一个基本技巧是用宏覆盖 trow 函数。 这样做会导致我们还覆盖库中所有包含的 trow 运算符的问题,这不是一个好的解决方案(而且也不起作用)。 您可能知道,如果您包含 header,它将只包含一次(主要是感谢 header 守卫)。 所以这里的技巧是包含库包含的 headers,而不是覆盖目标库的 header,而实际上并不包含它们的 header再次是因为我们已经这样做了。
无论如何,在 MSVC 中,您的 throw(...) 说明符始终是有效的白色 space。例如,Visual Studio 总是默默地编译一个像这样的函数:
void SomeFunction() throw(std::string) {...}
好像是:
void SomeFunction() {...}
或在现代 C++11 之后:
void SomeFunction() noexcept(false) {...}
因此,对于 99% 的跨平台 3P 包,宏和 #include hacks 集中在:
#define throw(...)
将立即运行,因为包的本机 Windows 构建已经在默默地执行该宏所做的事情。如果做不到这一点,您可以将所有调用和对有问题的接口的引用包装在您自己的几个 C++14 源文件中。这至少会让你的项目的其余部分使用 c++17。