C++ 模块、标准库、第三方库和单一定义规则

sud*_*dgy 9 c++ one-definition-rule language-lawyer c++20 c++-modules

每一两年我都会决定尝试使用 C++ 模块,但每次我都会遇到问题,通常是与编译器有关。但这一次我的问题似乎出在规范本身,而且我似乎找不到解决方法。

考虑一个带有 header 的第三方库foo.hpp。中foo.hpp,它包括<string>. 假设由于某种原因(可能是因为奇怪的宏使用),foo.hpp无法将其编译为标头单元,因此必须将其编译为#included。<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++ 标准不允许这样做,但所有实现正在共同努力以实现解决方法”,我会接受另一个答案。

这个问题以稍微不同的方式遇到了同一个问题,但问题是关于识别问题,而不是解决问题。提问者表示他们会发布另一个有关如何解决该问题的问题,但从未这样做。 这个问题问的基本上是同一件事,但它没有重点,似乎每个人都误解了他们所问的内容。

cpp*_*ner 3

标准说([std.modules]/5):

标准库中的声明表示同一实体,无论它是通过包含标头、导入标头单元还是导入 C++ 库模块使其可访问。

#include因此,如果混合并且不能很好地工作,这是一个实现错误import(据我所知,这是一个难以修复的错误)。