#include <iostream>
#include <memory>
// a dummy QDebug class, don't have QT installed here
class QDebug {};
QDebug& qDebug() {
static QDebug obj;
return obj;
}
template <typename T>
QDebug& operator <<(QDebug &os, const T &value) {
std::cout << "QDebug: " << value << std::endl;
return os;
}
// end dummy class
class ILoggableValue {
public:
virtual ~ILoggableValue() = default;
virtual void log(QDebug &os) const = 0;
virtual void log(std::ostream &os) const = 0;
};
template <typename T>
class LoggableValue : public ILoggableValue {
public:
LoggableValue(const T &value) : value{value} {}
void log(QDebug &os) const override {
// implementation of log for QDebug goes here
os << value;
}
void log (std::ostream &os) const override {
// implementation of log for std::ostream goes here
os << value << std::endl;
}
private:
const T &value;
};
class IHandler {
public:
virtual ~IHandler() = default;
virtual void log(const ILoggableValue &tolog) const = 0;
};
class CLHandler : public IHandler {
public:
explicit CLHandler(std::ostream &out) : out{out} {}
void log(const ILoggableValue &tolog) const override {
tolog.log(out);
}
private:
std::ostream &out;
};
class UIHandler : public IHandler {
public:
void log(const ILoggableValue &tolog) const override {
tolog.log(qDebug());
}
};
class Logger {
public:
Logger(std::unique_ptr<IHandler> h) : handler(std::move(h)) {}
template <class T>
void log(const T& tolog) { handler->log(LoggableValue<T>(tolog)); }
void setHandler(std::unique_ptr<IHandler> &h) { handler = std::move(h); }
const IHandler &getHandler() const { return *handler; }
private:
std::unique_ptr<IHandler> handler;
};
// example
void example(Logger &logger) {
logger.log(5);
logger.log("ABC");
logger.log(4.2);
}
int main() {
Logger qLogger{std::make_unique<UIHandler>()};
example(qLogger);
Logger stdoutLogger{std::make_unique<CLHandler>(std::cout)};
example(stdoutLogger);
}