What I would recommend doing is a class that wraps around iostream as follows:
#include <iostream> #define LOG Log() class Log { public: Log(){} ~Log() { // Add an newline. std::cout << std::endl; } template<typename T> Log &operator << (const T &t) { std::cout << t; return * this; } };
Then, when you want to change where the data goes, you simply change the behavior of the class. This is how you use the class:
LOG << "Use this like an iostream.";
[edit] As a suggested potato, I will add an example with something other than cout:
#include <sstream>
As for why you should try this instead of inheriting from something like a streaming stream, mainly because you can easily change where the Logger outputs will be dynamically. For example, you can have three different output streams and use a static member variable to exchange between them at runtime:
class Log { private: static int outputIndex = 0; // Add a few static streams in here. static std::stringstream bufOne; static std::stringstream bufTwo; static std::stringstream bufThree; public: // Constructor/ destructor goes here. template<typename T> Log &operator << (const T &t) { // Switch between different outputs. switch (outputIndex) { case 1: bufOne << t; break; case 2: bufTwo << t; case 3: bufThree << t; default: std::cout << t; break; } return * this; } static void setOutputIndex(int _outputIndex) { outputIndex = _outputIndex; } }; // In use LOG << "Print to stream 1"; Log::setOutputIndex(2); LOG << "Print to stream 2"; Log::setOutputIndex(3); LOG << "Print to stream 3"; Log::setOutputIndex(0); LOG << "Print to cout";
This can be easily expanded to create a powerful logging method. You can add filestreams, use std :: cerr etc.
Darcy rayner
source share