对同一文件的不同部分使用不同的 C++ 标准
Posted
技术标签:
【中文标题】对同一文件的不同部分使用不同的 C++ 标准【英文标题】:Using different C++ standard for different parts of the same file 【发布时间】: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。
【参考方案1】:
从理论上讲,这是可能的。用不同的标准编译文件的不同部分是有效地分割文件并为每个部分使用不同的后端。它不应该那么难。但是有一个很大的警告 - ABI 兼容性。当您意识到链接使用不同标准编译的目标文件通常是不可能的时,您会发现整个想法是一个地雷。编译器必须要么保持 ABI 稳定(这很好,但是每个标准都进行了大量的更改,保持 ABI 在它们之间兼容将是一场噩梦)或者以某种方式翻译不同标准的 ABI(这也将是我想是噩梦)。即使是现在,“检查”ABI 问题最流行的方法是使用extern "C"
来避免大惊小怪。
所以答案是 - 从理论上讲是可能的,但这种选择的实际影响是如此巨大,以至于不值得。
【讨论】:
以上是关于对同一文件的不同部分使用不同的 C++ 标准的主要内容,如果未能解决你的问题,请参考以下文章