#include <iostream>
// stub logging object to make the example work - just logs to stdout
struct Log
{
template<typename T>
friend Log& operator<<(Log& l, T d)
{
std::cout << d;
return l;
}
friend Log& operator<<(Log& l, std::ostream& (*f)(std::ostream&))
{
std::cout << f;
return l;
}
};
Log gLog;
#define LOG Base::GetLog()
// GetLog in the global namespace for non-Context derived classes, free functions etc
struct Base {
static Log& GetLog()
{
return gLog;
}
};
// classes derive from this to add context specific information when logging
template <typename Self>
struct Context
{
// this GetLog adds prefix to Context derived classes
Log& GetLog()
{
static_cast<const Self*>(this)->Token(gLog); // add the Context's Token to the log
return gLog << ": ";
}
};
//-------------------------
template<typename T>
struct Foo : Context<Foo<T>>
{
typedef Context<Foo<T>> Base;
void Func1()
{
LOG << __func__ << std::endl;
}
void Func2()
{
LOG << __func__ << std::endl;
}
Log& Token(Log& l) const { return l << "Foo"; }
};
// logging inside a non-Context derived class
struct Bar
{
void Func()
{
LOG << __func__ << std::endl;
}
};
// logging inside a free function
void Baz()
{
LOG << __func__ << std::endl;
}
//-------------------------
int main()
{
Foo<int> f;
f.Func1();
f.Func2();
Bar b;
b.Func();
Baz();
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKLy8gc3R1YiBsb2dnaW5nIG9iamVjdCB0byBtYWtlIHRoZSBleGFtcGxlIHdvcmsgLSBqdXN0IGxvZ3MgdG8gc3Rkb3V0CnN0cnVjdCBMb2cKewogICAgdGVtcGxhdGU8dHlwZW5hbWUgVD4KICAgIGZyaWVuZCBMb2cmIG9wZXJhdG9yPDwoTG9nJiBsLCBUIGQpCiAgICB7CiAgICAgICAgc3RkOjpjb3V0IDw8IGQ7CiAgICAgICAgcmV0dXJuIGw7CiAgICB9CiAgICBmcmllbmQgTG9nJiBvcGVyYXRvcjw8KExvZyYgbCwgc3RkOjpvc3RyZWFtJiAoKmYpKHN0ZDo6b3N0cmVhbSYpKQogICAgewogICAgICAgIHN0ZDo6Y291dCA8PCBmOwogICAgICAgIHJldHVybiBsOwogICAgfQp9OwpMb2cgZ0xvZzsKCiNkZWZpbmUgTE9HIEJhc2U6OkdldExvZygpCgovLyBHZXRMb2cgaW4gdGhlIGdsb2JhbCBuYW1lc3BhY2UgZm9yIG5vbi1Db250ZXh0IGRlcml2ZWQgY2xhc3NlcywgZnJlZSBmdW5jdGlvbnMgZXRjCnN0cnVjdCBCYXNlIHsKICAgIHN0YXRpYyBMb2cmIEdldExvZygpCiAgICB7CiAgICAgICAgcmV0dXJuIGdMb2c7CiAgICB9Cn07CgovLyBjbGFzc2VzIGRlcml2ZSBmcm9tIHRoaXMgdG8gYWRkIGNvbnRleHQgc3BlY2lmaWMgaW5mb3JtYXRpb24gd2hlbiBsb2dnaW5nCnRlbXBsYXRlIDx0eXBlbmFtZSBTZWxmPgpzdHJ1Y3QgQ29udGV4dAp7CiAgICAvLyB0aGlzIEdldExvZyBhZGRzIHByZWZpeCB0byBDb250ZXh0IGRlcml2ZWQgY2xhc3NlcwogICAgTG9nJiBHZXRMb2coKQogICAgewogICAgICAgIHN0YXRpY19jYXN0PGNvbnN0IFNlbGYqPih0aGlzKS0+VG9rZW4oZ0xvZyk7IC8vIGFkZCB0aGUgQ29udGV4dCdzIFRva2VuIHRvIHRoZSBsb2cKICAgICAgICByZXR1cm4gZ0xvZyA8PCAiOiAiOwogICAgfQp9OwoKLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpzdHJ1Y3QgRm9vIDogQ29udGV4dDxGb288VD4+CnsKICAgIHR5cGVkZWYgQ29udGV4dDxGb288VD4+IEJhc2U7CiAgICAKICAgIHZvaWQgRnVuYzEoKQogICAgewogICAgICAgIExPRyA8PCBfX2Z1bmNfXyA8PCBzdGQ6OmVuZGw7CiAgICB9CiAgICB2b2lkIEZ1bmMyKCkKICAgIHsKICAgICAgICBMT0cgPDwgX19mdW5jX18gPDwgc3RkOjplbmRsOwogICAgfQoKICAgIExvZyYgVG9rZW4oTG9nJiBsKSBjb25zdCB7IHJldHVybiBsIDw8ICJGb28iOyB9Cn07CgovLyBsb2dnaW5nIGluc2lkZSBhIG5vbi1Db250ZXh0IGRlcml2ZWQgY2xhc3MKc3RydWN0IEJhcgp7CiAgICB2b2lkIEZ1bmMoKQogICAgewogICAgICAgIExPRyA8PCBfX2Z1bmNfXyA8PCBzdGQ6OmVuZGw7CiAgICB9Cn07CgovLyBsb2dnaW5nIGluc2lkZSBhIGZyZWUgZnVuY3Rpb24gCnZvaWQgQmF6KCkKewogICAgTE9HIDw8IF9fZnVuY19fIDw8IHN0ZDo6ZW5kbDsKfQoKLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgppbnQgbWFpbigpCnsKICAgIEZvbzxpbnQ+IGY7CiAgICBmLkZ1bmMxKCk7CiAgICBmLkZ1bmMyKCk7CgogICAgQmFyIGI7CiAgICBiLkZ1bmMoKTsKCiAgICBCYXooKTsKCiAgICByZXR1cm4gMDsKfQ==