如何 "flag" 相当于 "export" 到编译器预模块?

How to "flag" the equivalent of "export" to the compiler pre-modules?

假设我有以下文件:

simulate.h:

#ifndef SIMULATE_H
#define SIMULATE_H

#include "my_data_type.h"

MyDataType Simulate ();

#endif

simulate.cpp:

#include "simulate.h"
// include lots of other things
// define lots of functions and new classes to solve sub-problems
// finally we define the "Simulate" function, which is the **only** thing we want to export.

现在,假设我们有很多像上面那样的 header/cpp 文件对(在 cpp 文件之外不需要大量 functions/data 类型)。

我是否认为这会为编译器和链接器带来不必要的开销? 据我了解,编译器不知道其他目标文件不会使用什么,因此这会创建更多臃肿的 .o 文件,从而减慢链接器的速度,对吗?

我知道 modulesc++20 中解决了很多这些问题,但是在 c++17 中是否有一些标准的解决方法?

我能想到一种方式似乎可以告诉编译器 引入的 functions/data 类型不会被重用:将它们包装在一个class,将所有内容都放在 private 部分,只向 public 公开一种方法。然而,这是超级 hacky 和丑陋的。

As I understand it, the compiler can't know what won't be used by other object files, so this would create more bloated .obj files and thereby slow down the linker, is that right?

从广义上讲...没有。

代码 必须 在 .o 文件中,因为您“导出”的代码使用它。可执行文件传递使用的任何代码都必须编译并存储在 some 目标文件中。所以它必须在某个地方,编译器必须读取它并将它存储在可执行文件中。

至于它是否会减慢链接器的速度,他们非常善于找到他们正在寻找的特定代码。我的意思是是的,一些编译器可能会将整个文件加载到内存中,因此更大的 .o 将需要更长的时间来加载。但同样,您的“导出”函数使用了该代码,所以它仍然很重要。

正如 Jarod42 在评论中指出的那样,我们可以使用 unnamed/anonymous 命名空间,其内容无法从其他翻译单元访问 (N3797: 7.3.1.1):

An unnamed-namespace-definition behaves as if it were replaced by

inline /*opt*/ namespace unique { /* empty body */ }
using namespace unique;
namespace unique { namespace-body } 

where inline appears if and only if it appears in the unnamed-namespace-definition, all occurrences of unique in a translation unit are replaced by the same identifier, and this identifier differs from all other identifiers in the entire program.

因此我们可以使用它来告诉编译器什么是我们翻译单元的本地内容:

namespace // Sub-problem stuff:
{
// ... classes
// ... functions
}

// Export stuff:
// ... classes
// ... functions

这样编译器只绑定到“导出”的正确行为,所以可以做一些事情,比如删除一些已经内联的子问题函数。