代码之家  ›  专栏  ›  技术社区  ›  Pustovalov Dmitry

c++1z动态异常规范错误

  •  19
  • Pustovalov Dmitry  · 技术社区  · 8 年前

    我试图用新的GCC版本7.2.1编译我的项目,但在动态异常规范方面有一个问题:

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

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

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

    5 回复  |  直到 8 年前
        1
  •  14
  •   Barry    8 年前

    P0003 . 在此之前,它们自C++11以来就一直被弃用。它们不再是语言的一部分,因此没有真正的方法来修复它。只要您需要第三方库,直到它发生变化,您就只能使用C++14。


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

    #define throw(...)
    

    但我不推荐。

        2
  •  10
  •   WolverinDEV    6 年前

    我写了一个小的变通方法。

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

    一个基本技巧是用宏覆盖trow函数。 这样做会导致我们遇到一个问题,即我们还为库中的所有包含重写trow运算符,这不是一个好的解决方案(也不起作用)。 这里的技巧是包含库中包含的头,而不是覆盖目标库的抛出包含头,因为我们已经包含了头,所以目标库实际上不再包含它们的头。

        3
  •  2
  •   cocheci    8 年前

    遇到了同样的问题,所以我不得不在/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
  •  2
  •   Nehal J Wani    7 年前
    1. 上述注释中提到的隔离层。类似于:

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

     void fn() throw (int) { }
    

    #endif // __cplusplus

    1. 现在是你开始替换的时候了 throw(whatever) 具有 noexcept(false) .

    无论哪种方式,都要准备好玩一玩!

        5
  •  1
  •   user3726672    6 年前

    在MSVC中你的投掷(…)说明符始终是有效的空白。与中一样,Visual Studio始终以静默方式编译以下函数:

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

    好像是:

    void SomeFunction() {...}
    

    或者在现代C++11以后的版本中:

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

    因此,对于99%的跨平台3P软件包,宏和#包括围绕以下内容的黑客攻击:

    #define throw(...) 
    

    将立即工作,因为包的本机Windows版本已经在默默地执行该宏所做的操作。否则,您可以打包所有通话&在您自己的几个C++14源文件中引用了有问题的接口。这至少可以让项目的其余部分使用c++17。