Domanda

i'm trying to write a logging class where you will be able to do something like this

//Create an instance of a class
Log log;

log.debug() << "a string " << 42 << endl;
log.info() << "another string " << 41 << endl;

This will produce the following output to stdout

Info: a string 42
Debug: another string 41

Here is what i have been able to achieve so far

#include <iostream>
#include <string>
#include <sstream>

#define endl '\n'

using std::cout;
using std::string;
using std::stringstream;

class Log {
    public:
        Log () {}
       ~Log() {}

        //Create buffer to store everything
        stringstream buffer;

        //Create templase class to overload <<
        template <class T>
        inline Log & operator << (T data) {
                buffer << data;
                return *this;
        }

        inline Log & debug() {
                print("Debug: ");
        } 

        inline Log & info() {
                print("Info: ");
        }

        inline void print(string type) {
                //Display the contents of the buffer to standard output
                cout << type << buffer.str();
                //Clear the buffer
                buffer.str(string());
        }
};

int main() {
        Log log;
        log << "Hello " << "World " << 5 << " " << 2.3 << endl;
        log.debug();

        log << "Hello Again " << 42 << endl;
        log.info();
        return 0;
}

This produces the correct output but this way each line of logging takes up two lines of code and is very cumbersome. Can anyone thing off a way I can do log.debug() << "stuff"? This is a very simple example, in later versions, instead of just a string there will be time stamps, date stamps, usernames etc. which is why i'm trying to get each log level handled by a different function.

I am guessing I'll need another operator overload statement but i just can't figure out what it needs to be. Also the current << template operator doesn't like std::endl (wont compile if i use it) so I just set endl = '\n' at the top.

Thanks in advance, looking forward to learning as much as possible.

È stato utile?

Soluzione

It sounds like what you want is for your debug and info functions to return something like a std::stringstream that will support operator<<, but somehow also flush the output afterwards. If that's it, you would be better off using something like a variadic template function.

As for your other issue, std::endl is actually a template, so its type cannot be used as T for Log::operator<< <T> (T). This is one example of why it's not worth trying to reimplement the stream functionality. The overload which lets you write << std::endl is declared something like template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits> & operator<<(basic_ostream<_CharT, _Traits>&, basic_ostream<_CharT, _Traits> &(basic_ostream<_CharT, _Traits> &)). std::endl is a function template which takes an ostream, appends a newline, and flushes the stream.

I should also note that your debug and info functions are not returning a value. If you're using GCC, the warning for this is disabled by default but it can be a very tricky source of undefined behavior. Use -Wreturn-type to enable it when you build something important.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top