c++ - 传递可变参数
问题描述
下面是一个简单的记录器类,我实现了我的项目。
/* g++ test.cpp -o test */
#include <fstream>
#include <string>
#include "fmt/fmt.h"
typedef enum Severity
{
LOG_INFO = 0,
LOG_WARNING,
LOG_ERROR
} Severity;
class Logger
{
public:
Logger(const std::string &log_file);
~Logger();
template <typename... Args> void DoLog(Severity severity, const std::string& context, fmt::format_string<Args...> fmt, Args&&...args);
private:
std::ofstream fout;
};
static const std::string severity_str[3] = {
"INFO",
"WARNING",
"ERROR"
};
Logger::Logger(const std::string &log_file)
{
fout.open(log_file, std::ofstream::out | std::ofstream::trunc);
}
Logger::~Logger()
{
fout.close();
}
template <typename... Args>
void Logger::DoLog(Severity severity, const std::string& context, fmt::format_string<Args...> fmt, Args&&...args)
{
fout << fmt::format("[{:<7}] [{}] {}", severity_str[severity], context, fmt::format(fmt, std::forward<Args>(args)...)) << std::endl;
}
int main()
{
Logger log("log.txt");
log.DoLog(LOG_INFO, "0", "Yo");
log.DoLog(LOG_INFO, "1", "Hello {}", 42);
log.DoLog(LOG_ERROR, "2", "Word {0:02X}", 0xFF);
log.DoLog(LOG_WARNING, "3", "! {} {}", 4, 5);
uint8_t opcode = 0xDD;
log.DoLog(LOG_ERROR, "CPU::HandlePrefixCB", "Unknown opcode: {0:02X}", opcode);
uint8_t &ref = opcode;
log.DoLog(LOG_ERROR, "CPU::HandlePrefixCB", "Unknown opcode: {0:02X}", ref);
return 0;
}
即使这个文件编译和运行没有问题,当我将它们添加到我的项目代码库并编译时,g++ 会输出一堆未定义的引用,如下所示
C:/TDM-GCC-64/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: obj/CPUOpcodes.o:CPUOpcodes.cpp:(.text+0xf47): undefined reference to `void Logger::DoLog<unsigned char&>(Severity, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, fmt::v8::basic_format_string<char, fmt::v8::type_identity<unsigned char&>::type>, unsigned char&)'
C:/TDM-GCC-64/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: obj/CPUOpcodes.o:CPUOpcodes.cpp:(.text+0x3011): undefined reference to `void Logger::DoLog<unsigned char&>(Severity, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, fmt::v8::basic_format_string<char, fmt::v8::type_identity<unsigned char&>::type>, unsigned char&)'
...
fmt::format_string<Args...> fmt, Args&&...args
我怀疑问题在于我如何处理DoLog
. 我找不到任何问题。有什么我需要解决的吗?
解决方案
DoLog 的第三个参数应该只是一个字符串(我将输出更改为 std::cout 进行测试)
#include <map>
#include <iostream>
#include <string>
#include <fmt/format.h>
typedef enum Severity
{
LOG_INFO = 0,
LOG_WARNING,
LOG_ERROR
} Severity;
static const std::string severity_str[3] =
{
"INFO",
"WARNING",
"ERROR"
};
class Logger
{
public:
Logger() = default;
~Logger() = default;
template<typename... args_t>
void DoLog(Severity severity, const std::string& context, const std::string& fmt, args_t&&... args)
{
std::cout << fmt::format("[{:<7}] [{}] {}", severity_str[severity], context, fmt::format(fmt, std::forward<args_t>(args)...)) << std::endl;
}
};
int main()
{
Logger log;
log.DoLog(LOG_INFO, "0", "Yo");
log.DoLog(LOG_INFO, "1", "Hello {}", 42);
log.DoLog(LOG_ERROR, "2", "Word {0:02X}", 0xFF);
log.DoLog(LOG_WARNING, "3", "! {} {}", 4, 5);
uint8_t opcode = 0xDD;
log.DoLog(LOG_ERROR, "CPU::HandlePrefixCB", "Unknown opcode: {0:02X}", opcode);
uint8_t& ref = opcode;
log.DoLog(LOG_ERROR, "CPU::HandlePrefixCB", "Unknown opcode: {0:02X}", ref);
return 0;
}
推荐阅读
- java - 当达到特定分数时,如何在我的骰子游戏中添加警报对话框?Java、安卓工作室
- javascript - 即使我在浏览器控制台中看到它,也无法按 className 抓取元素
- mysql - 如何从 golang MySQL 包中获取精细的 LOAD DATA 结果?
- python - 如何在本地主机上的发布请求中显示烧瓶中的数据?错误:分配前引用了局部变量“reqData”
- jekyll - jekyll 主页标题为空
- python-3.x - 为许多列表以垂直顺序打印列表中的值
- python - Discord.py - 每天运行一次命令
- c++ - Process()中grpc::AuthContext、consumed_auth_metadata和response_metadata的作用是什么?
- multithreading - Kafka Streams:处理器、serdes 等的线程安全
- delphi - 如何在 Delphi 中最大化最小化窗口(如果它在 SYSTEM 下运行)