So basically I'm looking for a way to create an interface with various implementations for different platforms. Normally this would be quite straight forward, but I'm wanting to create an interface for a logger, and being able to have functions such as below is my goal:
class Log {
public:
template<typename ...Args>
virtual void log(const char* fmt, const Args&... args) const = 0;
template<typename ...Args>
virtual void warn(const char* fmt, const Args&... args) const = 0;
template<typename ...Args>
virtual void error(const char* fmt, const Args&... args) const = 0;
};
Now obviously this doesn't work as you can't have pure virtual templated functions.
One approach I saw was to make the Log class a CRTP (curiously recurring template pattern) class and use something like the following to get the desired behavior:
//Log.h (template<typename T> class Log {...})
template<typename ...Args>
void log(const char* fmt, const Args&... args) const {
//the following line would essentially downcast the 'this' pointer and
//call it's version of log instead...
reinterpret_cast<T*>(this)->log(fmt, args...);
}
//ExampleLog.h (class ExampleLog : public Log<ExampleLog> {...})
template<typename ...Args>
void log(const char* fmt, const Args&... args) const {
m_logger->log(fmt, args...);
}
The downside is that this make the interface awkward to use, constantly needing to use Log<Impl>
where the Impl
(implementation) may not be known/exposed.
I'm really lost on how I can go about creating an interface that includes function which have a variable number and type of parameters... ?