我有一个很大的遗留c++代码库,使用hpp/cpp文件中的头和实现。这需要仍然可用,以兼容旧的编译器。
示例文件
// myLib.hpp
int foo();
// myLib.cpp
#include "myLib.hpp"
int foo() { return 42; }
// main.cpp
#include "myLib.hpp"
int main() { return foo(); }
字符串
对于较新的编译器,我希望能够将特定的头文件编译成模块(例如“myModule”)。就像围绕hpp/cpp文件的 Package 器。这不应该是一个替代,因为一些依赖的翻译单元可能仍然使用#include "myLib.hpp"
,而其他人可能已经使用import myModule;
。
如果一个模块应该被构建和使用,可以通过一个CMake选项来选择,该选项被转换为一个预处理器宏,例如。
# CMakeLists.txt
option(CMAKE_USE_MODULES "Enable C++20 module usage" ON)
if(CMAKE_USE_MODULES)
add_compile_definitions(USE_MODULES)
endif(CMAKE_USE_MODULES)
型
我的问题是模块接口及其实现应该如何实现?
// myLib.hpp
EXPORT int foo();
// myLib.cpp
#define EXPORT
#include "myLib.hpp"
int foo() { return 42; }
// myModule.cpp
export module myModule;
#define EXPORT export
#include "myLib.hpp"
// myModule_impl.cpp
module myModule;
#include "myLib.cpp"
型
其他翻译单元现在可以选择使用头或模块,例如。
// tu_alwaysHeader.cpp
#define EXPORT
#include "myLib.hpp"
int alwaysHeader() { return foo(); }
// tu_tryModuleOtherwiseHeader.cpp
#ifdef USE_MODULES
import myModule;
#else
#define EXPORT
#include "myLib.hpp"
#endif
int tryModuleOtherwiseHeader() { return foo(); }
型
另一个问题:CMake中的依赖关系应该如何表示?特别是myModule.cpp到myLib.hpp,myModule_impl.cpp到myLib.cpp?
godbolt上的最小示例。
1条答案
按热度按时间xfb7svmp1#
这不应该是一个替代,因为一些依赖的翻译单元可能仍然使用
#include "myLib.hpp"
,而其他的可能已经使用import myModule;
。这是个问题
C++模块不仅仅是访问实体的一种替代方式。将实体声明/定义放在模块的范围内会改变该实体的性质。具体来说,它现在具有模块链接。
命名同一实体的两个声明必须在该实体的链接上达成一致。无论它们是在你的整个程序中声明的,而不仅仅是在一个文件中。
围绕这一点有几条规则,但它们几乎总是归结为同一件事:格式错误,不需要诊断。这意味着您的代码可以编译和链接,但接下来发生的事情是不可知的。它可能工作......直到它不工作。
一个库可以have a module and non-module build for itself。但是你必须把它们当作库的不同版本。不同的,* 不兼容的 * 版本。你程序中的所有代码都必须同意使用哪个版本。