假设我使用的库在其标头中有这样的声明:
#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)
的声明。
不是。
考虑库标头之一中的以下声明:
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
是类型系统的一部分,因此必须用某些符号表示。