Visual C++使用Modules与Concepts时出现Unresolved External Symbol错误
问题原因
你的链接错误是模板隐式实例化规则和C++ Modules的可见性规则共同导致的:
engine::game是模板类,C++中模板的隐式实例化要求调用点必须能看到模板成员函数的完整定义,才能生成对应类型参数的实例符号- 你将
play()的实现放在了game.cxx这个模块实现单元中,模块实现单元内的代码默认对其他翻译单元不可见,main函数编译时看不到play()的实现,无法生成engine::game<engine::text_ui>::play()的实例,链接时就会报未解析外部符号的错误。
解决方案
推荐两种常用修复方式,按需选择即可:
方案1:模板实现移到模块接口(最常用)
直接把play()的实现放到game.ixx的模块接口单元中,让所有导入模块的翻译单元都能看到模板定义,自动完成实例化:
修改game.ixx中的game类定义,直接内联实现play():
namespace engine { export template<typename ui_t> requires std::derived_from<ui_t, ui> class game { std::string name; ui_t ui; public: game(std::string name) : name{name} {}; // 直接在接口中实现play void play() const { ui.notify(name + " is being played.\n"); } }; }
改完之后可以删除game.cxx里的play()实现代码,或者直接删掉game.cxx文件即可。
方案2:显式实例化模板特化
如果你一定要将模板实现和接口分离,可以在game.cxx末尾添加对应类型的显式实例化声明,让编译器在编译game.cxx时直接生成对应实例的符号:
在game.cxx的engine命名空间外添加:
template class engine::game<engine::text_ui>;
这种方案的缺点是后续每新增一种ui_t的实现类型,都需要手动添加对应的显式实例化声明,灵活性较低。
内容的提问来源于stack exchange,提问作者Wungi
相关产品推荐
相关产品推荐

