全局模块片段中的头文件包含未传递到其他文件
全局模块片段中的头文件包含未传递到其他文件
我之前写C模块的时候也踩过一模一样的坑!你看,你在Utils:JsonSerializable模块开头用了全局模块片段(就是module;那行开始的部分)包含了一堆头文件,但这些头文件的内容根本不会被导出到其他导入这个模块的文件里——这可是C模块设计时就定好的规则。
先给你理清楚为啥会这样:全局模块片段的作用说白了就是给模块内部用的,专门用来兼容那些还没改成模块的传统头文件,让它们能在模块编译单元里正常工作,但这些头文件里的类型、函数啥的,只会在当前模块的编译单元里可见,其他导入你这个模块的代码完全看不到。就像你在房间里放了个东西,没把门打开,外面的人自然拿不到。
那怎么解决呢?其实很简单,把需要让其他文件能用的头文件,从全局模块片段里移到export module语句之后,还要确保它们能被导出:
举个例子,你原来的代码里用了nlohmann::json作为接口的一部分(比如toJson()的返回值),那这个类型必须让导入模块的代码也能看到,所以得这么改:
module; // 这里只留模块内部自己用的头文件,比如<cerrno>、<streambuf>如果只是模块内部逻辑需要,就留在这 #include <cerrno> #include <streambuf> export module Utils:JsonSerializable; import Meta; import <string>; // 把需要对外暴露的头文件移到这里,用export #include让它们成为模块接口的一部分 export #include <nlohmann/json.hpp> export #include <nlohmann/json_fwd.hpp> export namespace utils { class JsonSerializable { public: virtual ~JsonSerializable() = default; virtual nlohmann::json toJson() const = 0; virtual PotentialError<ErrorString> fromJson(const nlohmann::json& json) = 0; }; }
如果你的编译器支持头单元(现在主流编译器比如GCC 11+、Clang 12+、MSVC 2022都支持了),那更推荐用头单元的方式导入并导出,这样编译效率更高:
module; #include <cerrno> #include <streambuf> export module Utils:JsonSerializable; import Meta; import <string>; // 用export import导入头单元,同时导出给模块使用者 export import <nlohmann/json.hpp>; export import <nlohmann/json_fwd.hpp>; export namespace utils { class JsonSerializable { public: virtual ~JsonSerializable() = default; virtual nlohmann::json toJson() const = 0; virtual PotentialError<ErrorString> fromJson(const nlohmann::json& json) = 0; }; }
最后再提醒你一句:别啥头文件都往外导,只导那些模块接口里真的用到、其他文件也需要的,不然会把模块的耦合度搞得很高,编译速度也会变慢。
内容来源于stack exchange
相关产品推荐
相关产品推荐

