C++模块中向SpdLog转发可变参数的问题求助
场景与需求
- 项目基于C++模块开发,用Meyers单例模式封装SpdLog日志库,目标是将SpdLog完全隐藏在Core共享库内,未来可替换日志库而无需修改客户端代码
- 客户端只需导入Logger模块即可调用日志接口,Core库静态链接SpdLog
期望客户端调用方式
import Logger; int main() { //调用单例封装类的静态方法 Logger::Info("{1} is a {0}", "test", "This"); }
直接调用SpdLog验证正常
直接调用SpdLog实例的info方法可正常运行:
directSpdlogInstance->info("{1} is a {0}", "test", "This");
SpdLog的info方法签名:
template <typename... Args> inline void info(format_string_t<Args...> fmt, Args &&...args);
尝试的实现方案及错误
方案1:无约束参数转发
实现代码:
template<typename...Args> void Logger::Info(Args&&... args) { //GetInstance()获取SpdLog实例 GetInstance()->info(std::forward<Args>(args)...); }
编译错误C7595:
'fmt::v9::basic_format_string<char,const char
(&)[32]>::basic_format_string': call to immediate function is not a
constant expression Nano C:\Dev\Nano\Projects\Core\src\Logger.cppm 30
方案2:启用SPDLOG_USE_STD_FORMAT后使用make_format_args
定义SPDLOG_USE_STD_FORMAT切换到标准库format,实现代码:
template<typename...Args> void Logger::Info(std::format_string<Args...> fmt, Args&&... args) { GetInstance()->info(fmt, std::make_format_args(args...)); }
编译错误C2664:
'void spdlog::logger::info<std::_Format_arg_store<_Context,const char
(&)[32]>>(std::basic_format_string<char,std::_Format_arg_store<_Context,const char (&)[32]>>,std::_Format_arg_store<_Context,const char (&)[32]>
&&)': cannot convert argument 1 from
'std::basic_format_string<char,const char (&)[32]>' to
'std::basic_format_string<char,std::_Format_arg_store<_Context,const
char (&)[32]>>'
with
[
_Context=std::format_context
] Nano C:\Dev\Nano\Projects\Core\src\Logger.cppm 34
方案3:启用SPDLOG_USE_STD_FORMAT后直接转发参数
修改实现为直接转发参数:
template<typename...Args> void Logger::Info(std::format_string<Args...> fmt, Args&&... args) { GetInstance()->info(fmt, std::forward<Args>(args)...); }
问题:模块编译成功,但调用该模块的控制台项目出现链接错误LNK1104:
cannot open file 'C:\Dev\Nano\bin\windows-Debug\Core\Core.lib'
Core.dll已生成,但无对应的lib文件,通常此情况表示DLL无导出内容。但已通过NN_API(即__declspec(dllexport))导出静态模板方法:
export class Logger { public: Logger(const Logger& other) = delete; template<typename...Args> NN_API static void Info(std::format_string<Args...> fmt, Args&&... args); ... }
客户端main函数已按预期调用该方法,需解决当前链接问题及之前的参数转发错误。
内容的提问来源于stack exchange,提问作者Todd Burch

