#include <iostream>
#include <sstream>
struct Statement;
struct Logger;
struct ComponentBase;
//------------------------------------------------------------------------------
struct ComponentBase {
mutable ComponentBase *next;
ComponentBase() : next(nullptr) { }
virtual std::string toString() = 0;
};
template <typename T>
struct Component : ComponentBase {
T value;
Component(T value) : value(value) { }
~Component() { }
virtual std::string toString() {
std::stringstream ss;
ss << value;
return ss.str();
}
};
struct ComponentIterator {
ComponentBase *ptr;
ComponentIterator(ComponentBase *ptr) : ptr(ptr) { }
ComponentBase &operator*() { return *ptr; }
void operator++() { ptr = ptr->next; }
bool operator!=(ComponentIterator &other) { return (ptr != other.ptr); }
};
//------------------------------------------------------------------------------
struct Statement {
Logger *logger;
ComponentBase *front;
ComponentBase *back;
ComponentIterator begin() { return front; }
ComponentIterator end() { return nullptr; }
template <typename T>
Statement(Logger &logger, Component<T> &component)
: logger(&logger), front(&component), back(&component) { }
~Statement();
template <typename T>
Statement &operator<<(Component<T> &&component) {
back->next = &component;
back = &component;
return *this;
}
};
//------------------------------------------------------------------------------
struct Logger {
template <typename T>
Statement operator<<(Component<T> &&component) {
return {*this, component};
}
virtual void log(Statement &statement) = 0;
};
Statement::~Statement() {
logger->log(*this);
}
//------------------------------------------------------------------------------
template <typename T>
Component<T const &> wrap(T const &value) {
return value;
}
template <size_t N>
Component<char const *> wrap(char const (&value)[N]) {
return value;
}
//------------------------------------------------------------------------------
struct MyLogger : public Logger {
virtual void log(Statement &statement) override {
for(auto &&component : statement) {
std::cout << component.toString();
}
std::cout << std::endl;
}
};
int main() {
std::string variable = "string";
MyLogger logger;
logger << wrap("Option ") << wrap(variable) << wrap(" is ") << wrap(42);
}