The below is a simple logger class I implemented my project.
/* 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;
}
Even though this file compiles and runs without problems, when I add them to my project codebase and compile, g++ outputs a bunch of undefined references like ones below
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&)'
...
I suspect the problem lies on how I handle varags fmt::format_string<Args...> fmt, Args&&...args
in DoLog
. I can't find anything wrong with it. Is there anything I should fix?