I try to create a macro that call a variadic function that uses a template. I use the following code, but the linker cannot resolve a call to the macro...
This code is part of the Logger class:
template< typename ... Args >
void Logger::logTrace(Args const& ... args)
{
std::ostringstream stream;
using List = int[];
(void)List{ 0, ((void)(stream << args), 0) ... };
BOOST_LOG_SEV(log_, trace) << stream.str();
}
The logger class:
class Logger {
public:
static Logger* getInstance(const char *logFile = "LogClient.log");
template< typename ... Args >
void logTrace(Args const& ... args);
private:
Logger(std::string fileName);
virtual ~Logger();
void initialize(std::string fileName);
static Logger* logger_; // singleton instance
};
and the macro:
#define LOG_TRACE(...) Logger::getInstance()->logTrace(__VA_ARGS__);
A call to the macro:
LOG_TRACE("A log with a number: %d", 5);
Thanks for your help!
EDIT AND SOLVE:
The problem was not related to variadic function or even macro, but with linking. Implement logTrace in the class definition resolve the problem.
code Working:
`The logger class:
class Logger {
public:
static Logger* getInstance(const char *logFile = "LogClient.log");
template< typename ... Args >
void logTrace(Args const& ... args)
{
std::ostringstream stream;
using List = int[];
(void)List{ 0, ((void)(stream << args), 0) ... };
BOOST_LOG_SEV(log_, trace) << stream.str();
}
private:
Logger(std::string fileName);
virtual ~Logger();
void initialize(std::string fileName);
static Logger* logger_; // singleton instance
};
and the macro:
#define LOG_TRACE(...) Logger::getInstance()->logTrace(__VA_ARGS__);
A call to the macro:
LOG_TRACE("A log with a number: %d", 5);
You may have called your macro (and thus the logTrace template function) in a source file where Logger::logTrace()
is declared but not defined/implemented (e.g.: in a source file where you included Logger.h
). The full definition of the logTrace template function is required for your macro to work.
I suggest you define the logTrace member function into the Logger class:
class Logger {
public:
static Logger* getInstance(const char *logFile = "LogClient.log");
template< typename ... Args >
void logTrace(Args const& ... args)
{ /* add implementation here */ }
...