dynamic
dynamic

Reputation: 48141

Stream manipulator with a simple Logger

So I have this simple C++ Logger class.

class Log{
public:
    Log(const int& msgLevel = 1){
        this->msgLevel = msgLevel;
    }

    template <class T>
    Log& operator<<(const T& v){
        if (msgLevel<=level) {
            std::cout << v;
        }
        return *this;
    }

    ~Log(){

    }

    static int level;
    int msgLevel;
};

int Log::level = 1;

I can use it like this:

Log(1)<<"My debug info: "<<otherVariable;

The problem is when I try to use endl:

Log(1)<<"My debug info: "<<otherVariable<<endl;

I get this error:

error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'Log' (or there is no acceptable conversion)

To solve this error I need to add another method to my class like this:

// For manipulators like endl
Log& operator<< (ostream& (*pf) (ostream&)) {
    if (msgLevel<=level) {
        cout << pf;
    }

    return *this;
}

But adding this method just to handle endl it seems a bit an overkill to me. Are there any better alternative?

Another alternative would be just to use "\n" instead of endl;

Upvotes: 2

Views: 174

Answers (1)

Vaughn Cato
Vaughn Cato

Reputation: 64308

Because endl is a function template, the simple version of operator<< isn't good enough, because there are multiple possible ways it could match by using different template arguments for endl. Adding the second overload is probably the best you can do.

You could, however, factor out the common logic, like this:

template <class T>
Log& operator<<(const T& v){ return write(v); }

Log& operator<<(ostream& (*v)(ostream&)){ return write(v); }


template <typename T>
Log& write(const T &v)
{
    if (msgLevel<=level) {
        std::cout << v;
    }
    return *this;
}

Upvotes: 1

Related Questions