3

I'm searching the best way to add a custom, initial message to all the messages that std::cout (or std::cerr) prints to console/file output.

For example, if I setup that this custom prompt message will be the string "[Log]", then a classic

std::cerr << "This is a log message" << std::endl;

will be printed in this way:

> [Log] This is a log message

Clearly I can obtain this behavior using

std::string PROMPT_MSG = "[Log]";
std::cerr << PROMPT_MSG << "This is a log message" << std::endl;

but I'd like a less invasive way.

Thanks in advance

eang
  • 1,615
  • 7
  • 21
  • 41
  • 1
    Simple answer is: You can't. You can however use a proper logging framework and use that instead, for example [Boost log](http://www.boost.org/doc/libs/1_54_0/libs/log/doc/html/index.html). – Some programmer dude Aug 09 '13 at 16:01

4 Answers4

8

You could write your own class:

#include <iostream>
#include <string>

class MyLogger
{
    std::ostream & out;
    std::string const msg;
public:
    MyLogger(std::ostream & o, std::string s)
    : out(o)
    , msg(std::move(s))
    { }

    template <typename T>
    std::ostream & operator<<(T const & x)
    {
        return out << msg << x;
    }
};

MyLogger MyErr(std::cerr, "[LOG] ");

Usage:

MyErr << "Hello" << std::endl;
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • This is interesting. But I need also the function `cout.rdbuf()`, does exist a similar way to redirect the output on a file with a custom class like this one? – eang Aug 09 '13 at 16:25
  • 2
    @ital: Please make a new question that describes the problem you're trying to solve. – Kerrek SB Aug 09 '13 at 16:27
5

As Joachim Pileborg suggested you can use a logging framework. YOu can use an existing one or start with your own that will contain just one class:

class MyLogger{}
template <typename T>
MyLogger& operator << (MyLogger& logger, const T& logStuff)
{
   std::cerr << PROMPT_MSG << logStuff << std::endl;
   return logger;
}

then define a global variable of class MyLogger:

MyLogger mylogger;

then when you want to write a log record, write:

mylogger << "This is a log message";

overloaded operator << of class MyLogger will do what you want;

mvidelgauz
  • 2,176
  • 1
  • 16
  • 23
  • @KerrekSB If you mean that it will add newline after each "a", "b" and "c" then you can remove '< – mvidelgauz Aug 09 '13 at 16:48
  • A few months ago I answered a similar qestion. I help the OP with implementing a custom logger. I used `std::endl` manipulator as sentinel to print the log prompt. Here is the code: https://github.com/Manu343726/Cpp11CustomLogClass – Manu343726 Aug 09 '13 at 17:42
2

I had the same problem in a recent project. I solved it with this little class:

class DebugOut
{
public:
static const int COLUMN_WIDTH = 15;
DebugOut(const std::wstring &type)
{
    std::wcout << type;
    for(int i=type.length();i<COLUMN_WIDTH;i++)
        std::wcout << " ";
    std::wcout << ": ";
}

~DebugOut()
{
    std::wcout << std::endl;
}
template <typename T>
friend DebugOut& operator<<(DebugOut& out,T i)
{
    std::wcout << i;
    return out;
}
};

Sample usage: DebugOut(L"Log") << "Something";

monoceres
  • 4,722
  • 4
  • 38
  • 63
0

I guess you could just define a function log and a function error, and then just call them when you want to print a log or error method. That way you don't have to add the PROMPT_MSG every time.

Svend Hansen
  • 3,277
  • 3
  • 31
  • 50