用 noexcept(...) 替换 throw(...) - ABI 跨语言标准安全?

问题描述 投票:0回答:1

假设我使用的库在其标头中有这样的声明:

#if __cplusplus >= 201703L
// C++17 or newer
    #define _NOTHROW noexcept(true)
    #define _THROWS(x) noexcept(false)
#else
    #define _NOTHROW throw()
    #define _THROWS(x) throw(x)
#endif

然后在 .h 文件中的函数声明和 .cpp 文件中的函数定义中使用上述宏。

使用 GCC 或 Clang 为 C++11 编译此库,然后将其标头包含在为 C++17 编译的应用程序中并(静态)链接它们是否安全?我知道,一般来说,对于 GCC 和 Clang,如果您使用完全相同的编译器版本来编译它们,那么在不同的 C++ 标准之间链接是安全的,但我想知道当编译 library 时是否存在问题(对于C++11) 函数被标记为

throw()
throw(some_exception_type)
,但是当编译主 application 时(对于 C++17),它看到了标有
noexcept(true)
noexcept(false)
的声明。

c++ c++11 gcc c++17 clang
1个回答
0
投票

不是。

考虑库标头之一中的以下声明:

void f() _NOTHROW;
void g(decltype(&f));

在 Linux ABI 上,g 在 C++11 中的损坏名称是

_Z1gPFvvE
,在 C++17 中是
_Z1gPDoFvvE
。 (参见此处)。

因此,如果

g
在库的源代码之一中定义(编译为 C++11),则定义的符号将为
_Z1gPFvvE
。如果
g
被编译为 C++17 的应用程序函数之一调用,它将尝试调用
_Z1gPDoFvvE
并且将无法链接。

最终,这是因为

noexcept
是类型系统的一部分,因此必须用某些符号表示。

© www.soinside.com 2019 - 2024. All rights reserved.