sud*_*dgy 9 c++ one-definition-rule language-lawyer c++20 c++-modules
每一两年我都会决定尝试使用 C++ 模块,但每次我都会遇到问题,通常是与编译器有关。但这一次我的问题似乎出在规范本身,而且我似乎找不到解决方法。
考虑一个带有 header 的第三方库foo.hpp
。中foo.hpp
,它包括<string>
. 假设由于某种原因(可能是因为奇怪的宏使用),foo.hpp
无法将其编译为标头单元,因此必须将其编译为#include
d。<string>
我的问题来自于尝试同时使用这个库。
想法#1:
module;
#include <foo.hpp>
export module A;
import <string>;
...
Run Code Online (Sandbox Code Playgroud)
据我了解,这里的问题是<string>
包含在 中,但是在导入 时不会应用foo.hpp
包含的标头防护,从而导致 odr 违规。<string>
<string>
想法#2:
export module A;
import <string>;
#include <foo.hpp>
...
Run Code Online (Sandbox Code Playgroud)
因为标头单元确实定义了宏,所以这修复了 odr 违规,当foo.hpp
包含时标头防护会启动<string>
。然而,这最终将 的所有内容定义foo.hpp
为 module 中的实体A
,这是不正确的并会导致各种问题。
想法#3:
module;
#include <foo.hpp>
export module A;
...
Run Code Online (Sandbox Code Playgroud)
这背后的想法是,如果foo.hpp
已经包含<string>
,为什么还要尝试再次获取它呢?问题是这在更复杂的情况下不起作用。是说我不是导入<string>
,而是导入了另一个导出导入的模块<string>
?或者也许是更复杂的事情?最终这个解决方案无法扩展。
想法#4:
module;
#include <string>
#include <foo.hpp>
export module A;
...
Run Code Online (Sandbox Code Playgroud)
这可行,但由于显而易见的原因并不理想。
我的问题是,有什么办法可以解决这个问题吗?或者 C++ 模块是否无法与非模块化的第三方库一起使用,这基本上使得 C++ 模块毫无用处?
请注意,我正在寻找 C++ 标准的规定,而不是任何特定实现的作用,因为实现仍在弄清楚它们在模块方面正在做什么。但是,如果其形式为“C++ 标准不允许这样做,但所有实现正在共同努力以实现解决方法”,我会接受另一个答案。
这个问题以稍微不同的方式遇到了同一个问题,但问题是关于识别问题,而不是解决问题。提问者表示他们会发布另一个有关如何解决该问题的问题,但从未这样做。 这个问题问的基本上是同一件事,但它没有重点,似乎每个人都误解了他们所问的内容。
标准说([std.modules]/5):
标准库中的声明表示同一实体,无论它是通过包含标头、导入标头单元还是导入 C++ 库模块使其可访问。
#include
因此,如果混合并且不能很好地工作,这是一个实现错误import
(据我所知,这是一个难以修复的错误)。