【问题标题】:c++1z dynamic exception specification errorc++1z动态异常规范错误
【发布时间】:2017-11-14 11:31:47
【问题描述】:

我正在尝试使用新的 GCC 版本 7.2.1 编译我的项目,但动态异常规范存在问题:

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

问题是这些错误来自我无法控制的第三方库。

有什么办法可以解决吗?据我所知,我不能告诉编译器用警告替换错误。使用 --std=c++14 不是一个选项,因为我想使用 C++1z 的新功能。

【问题讨论】:

标签: c++ c++17 exception-specification gcc7


【解决方案1】:

由于P0003,C++17 删除了动态异常规范。在此之前,它们自 C++11 以来已被弃用。它们不再是语言的一部分,所以没有办法修复它。只要您需要该第三方库,除非它发生变化,否则您将被困在 C++14 上。


如果你绝望了,你可以试试:

#define throw(...)

但我不会推荐它。

【讨论】:

  • 也许最好的方法是在库上设置一个隔离层(编译为 C++14),暴露 C++17 接口供程序使用?
【解决方案2】:

好吧,我写了一些解决方法。

#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,则分配器上不再允许 throw。 如果您仔细查看库的标题,您会发现定义了一个宏,其中包含库中默认分配器的定义。可悲的是,它不能被覆盖,因为它在那里被定义而忽略了可能已经被定义的东西。所以无论如何你都必须覆盖 trow。

一个基本技巧是用宏覆盖 trow 函数。 这样做会导致我们还覆盖库中所有包含的 trow 运算符的问题,这不是一个好的解决方案(而且也不起作用)。 你可能知道,如果你包含一个标题,它只会被包含一次(主要是由于标题保护)。 因此,诀窍是包含由库包含的标头,而不是覆盖目标库的 throw include 标头,因为我们已经这样做了,它实际上并没有再次包含它们的标头。

【讨论】:

  • 欢迎来到 SO!不鼓励仅使用代码的答案,因为它们无法深入了解问题是如何解决的。请更新您的解决方案,说明您的代码如何解决手头的问题:)
  • 是的,对不起,我添加了一个(简短的?)解释
【解决方案3】:

遇到了同样的问题,所以我不得不在 /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】:
    1. 如上面评论中提到的隔离层。比如:

    #if __cplusplus &lt; 201703L // Standards below C++2017

     void fn() throw (int) { }
    

    #endif // __cplusplus

    1. 现在是您开始用noexcept(false) 替换throw(whatever) 的时候了。

    不管怎样,准备好享受乐趣吧!

    【讨论】:

      【解决方案5】:

      在 MSVC 中,你的 throw(...) 说明符一直是有效的空白。如,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。

      【讨论】:

        猜你喜欢
        • 2018-05-23
        • 1970-01-01
        • 1970-01-01
        • 2013-01-14
        • 1970-01-01
        • 2013-09-15
        • 1970-01-01
        • 1970-01-01
        • 2020-03-04
        相关资源
        最近更新 更多