【发布时间】:2021-02-17 08:43:39
【问题描述】:
好的,我知道这听起来像是一个错误的问题,但让我在否决票开始之前解释一下:我们使用 C++11 作为我们开发的基线(针对多个平台)。最近需要在我们的代码库中进行一些更改,突然需要一些 C++17 功能。
到目前为止一切都很好,在我们的开发者平台上都可以很好地编译,但是在其中一个持续集成平台(Ubuntu 18.04)上我们遇到了一些错误,例如:
/usr/include/ev++.h:355:46: error: ISO C++1z does not allow dynamic exception specifications dynamic_loop (unsigned int flags = AUTO) throw (bad_loop)
(c++1z dynamic exception specification error 很好地解释了为什么会发生这种情况,并提供了一些关于如何使其消失的技巧)
但我开始思考(当然只是理论上)我们是否可以指定源文件的某些部分使用符合 C++11 的代码进行编译,而其他部分使用符合 C++17 的代码进行编译?
(澄清一下:不,我们不想升级,是的,我们已经解决了这个问题,我只是对理论方法感兴趣)
【问题讨论】:
-
“在我们的开发者平台上都编译得很好,但在其中一个持续集成平台(Ubuntu 18.04)上我们遇到了一些错误”我强烈 建议你使环境同质化。如果您的 CI 机器与开发人员环境不同,则可能会出现 很多 非常微妙的问题。尤其是编译器和标准库版本应该完全相同。使用包管理器中的库也是解决微妙问题的秘诀(也许 glibc 除外)。
-
不,不可能在同一个翻译单元的不同区域使用不同的C++标准。不过,您应该能够为不同的翻译单元使用不同的 C++ 标准。相应地重构您的代码。
-
你可以将文件的一半放在
#ifdef COMPILE_THIS中,另一半放在#ifdef NOW_COMPILE_THAT中,这与重构为两个文件基本相同,只是更混乱 -
对于这个问题 - 只需删除 throw (bad_loop) 或评论它:
// throw (bad_loop)。一般来说 - 似乎您需要为项目使用的所有编译器定义宏的 config.hpp - 定义宏。例如 - 查看 boost config.hpp -
从广义上讲,从可移植性的角度来看,您的请求看起来是不可能的。 C++ 不保证标准之间的 ABI 兼容性。从技术上讲,即使在其他 c++11 代码中来自 c++17 片段的函数调用也可能会生成不同的损坏符号,所以这不会链接。如果您使用 c++17 stl 方法并链接到 c++11 lib,您最终可能会丢失符号等。也就是说,如果我们谈论的是纯理论的可能性。实际上,gcc 在从某些版本的编译器(5.0?)开始的标准之间兼容 ABI。