Logging class and overloaded stream operators

R

Riku Jarvinen

Hello everyone,

I have a logging class which writes program outputs to the logfile. The
class works fine as long as only C++ native data types are considered. The
problem is that I have a program with a bunch of classes which have the
output stream operators << of their own. The overloaded operators work fine
when inserted into the std:cout stream but I don't know how to make the
logging class accept them.

If I try to compile the program (see the code below) with the command

mainlog << a;

included I get the following error message:
g++ logtest.cpp

logtest.cpp: In function `int main()':
logtest.cpp:64: error: no match for 'operator<<' in 'mainlog << a'
logtest.cpp:20: error: candidates are: Logger& Logger::eek:perator<<(const
char*)
logtest.cpp:25: error: Logger& Logger::eek:perator<<(int)
logtest.cpp:46: error: std::eek:stream&
operator<<(std::eek:stream&,
const MyClass&)

Does this mean I have to somehow introduce the overloaded operator << of
MyClass (and every other class I use in my program) separately in the Logger
class?

Here follows the simplified example:

------------------------------------
#include <iostream>
#include <fstream>

using namespace std;

class Logger
{
public:
Logger(const char* filename = "program.log")
{
logfile = new fstream(filename, fstream::eek:ut);
}
~Logger()
{
logfile->close();
delete logfile;
}

Logger& operator<<(const char* msg)
{
*logfile << msg;
return *this;
}
Logger& operator<<(const int val)
{
*logfile << val;
return *this;
}
private:
fstream* logfile;
};

class MyClass
{
public:
MyClass(const int n)
{
data = n;
}

~MyClass()
{
}

friend ostream& operator<<(ostream& o, const MyClass& v)
{
return o << "MyClass data = " << v.data << "\n";
}

private:
int data;
};

int main()
{
Logger mainlog;
MyClass a(10);

// These work fine
cout << a;
mainlog << "Bla " << 200 << "\n";

// This doesn't work
//mainlog << a;

return 0;
}
 
A

AnonMail2005

You need to define a template function in the Logger class so it can
accept all classes. Inside that function, it uses the operator<< to
output to a standard stream. This way, your classes don't need to
know specifically about a Logger class, just a standard stream.

It should be defined similiar to this:

template<class T>
friend Logger& operator<<(Logger& logger, const T& t)
{
logger.logfile_ << t;
return logger;
}

Also, check out log4cpp an open source logger based on log4j.
 
P

__PPS__

add
template<class T>
Logger& operator<<(const & T msg){
*logfile << msg;
return *this;
}

to your Logger class.

Or, you may inherit your Logger from std::eek:fstream if it does provide
some extra functionality over the Logger class you've posted (and in
this case you don't need to create any operators<<), otherwise just use
ostream
 
P

__PPS__

You need to define a template function in the Logger class so it can
accept all classes. Inside that function, it uses the operator<< to
output to a standard stream. This way, your classes don't need to
know specifically about a Logger class, just a standard stream.

It should be defined similiar to this:

template<class T>
friend Logger& operator<<(Logger& logger, const T& t)
{
logger.logfile_ << t;
return logger;
}

You cannot define this function in the Logger class - it's a
freestanding function. You must declare it friend to Logger also
 
A

AnonMail2005

You cannot define this function in the Logger class - it's a
freestanding function. You must declare it friend to Logger also

thanks, I was going to post a follow-up to my post but thought the
_friend_ specifier would be enough to clarify my statement.
 
P

__PPS__

Logger& operator<<(const & T msg){

it should be Logger& operator<<(const T & msg){
sorry
 
R

Riku Jarvinen

Riku said:
Hello everyone,

I have a logging class which writes program outputs to the logfile. The
class works fine as long as only C++ native data types are considered. The
problem is that I have a program with a bunch of classes which have the
output stream operators << of their own. The overloaded operators work
fine when inserted into the std:cout stream but I don't know how to make
the logging class accept them.

Thanks guys, template class solved the presented problem. However, I might
have simplified the case a little too much and I'm not sure if I'm able to
use the solution in my program. I have to study more about templates before
I proceed in this issue.
 
R

Riku Jarvinen

Riku said:
Thanks guys, template class solved the presented problem. However, I might
have simplified the case a little too much and I'm not sure if I'm able to
use the solution in my program. I have to study more about templates
before I proceed in this issue.

Ok, now I think it is time to ask something more about this logging issue.

So, the basic idea is to have a compact logger class which can be used like
the std::cout stream and add extra functionality to it (line numbering, some
output counters etc.). The class should also handle the manipulators,
including special manipulators in <iomanip>. How can I make the logging
class handle all the manipulators in the same way std::cout does?

Riku
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top