#include <iostream>
#include <iomanip>
//---------------------------------------------------------
template <typename TDerivedClass>
class AbstractLogger {
public:
void write(int x);
void write(double x);
template <typename T>
void writeLine(T x);
};
template <typename TDerivedClass>
void AbstractLogger<TDerivedClass>::write(int x) {
std::cout << x;
}
template <typename TDerivedClass>
void AbstractLogger<TDerivedClass>::write(double x) {
std::cout << std::setprecision(3) << x;
}
template <typename TDerivedClass>
template <typename T>
void AbstractLogger<TDerivedClass>::writeLine(T x) {
static_cast<TDerivedClass*>(this)->write(x);
std::cout << std::endl;
}
//---------------------------------------------------------
class Logger : public AbstractLogger<Logger> {};
//---------------------------------------------------------
class FooType1 {};
class FooType2 {};
class FooLogger : public AbstractLogger<FooLogger> {
public:
using AbstractLogger::write;
void write(FooType1 x);
void write(FooType2 x);
};
void FooLogger::write(FooType1 x) {
std::cout << "<value of type FooType1>";
}
void FooLogger::write(FooType2 x) {
std::cout << "<value of type FooType2>";
}
//---------------------------------------------------------
int main(int argc, char **argv) {
FooLogger log;
FooType1 foo1;
FooType2 foo2;
log.write(42); // OK
log.write(3.14159); // OK
log.write(foo1); // OK
log.write(foo2); // OK
std::cout << std::endl;
log.writeLine(42); // OK
log.writeLine(3.14159); // OK
log.writeLine(foo1); // OK
log.writeLine(foo2); // OK
}