473,473 Members | 1,808 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Logging class and overloaded stream operators [question #2]

Hi everyone,

I asked another question regarding this same subject about a week ago. See
thread:

http://groups.google.fi/group/comp.l...0bae667a479add

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 accept the iostream manipulators, including special
manipulators in <iomanip>. How can I make the logging class handle all the
manipulators in the same way std::cout does?

If I compile the code (see below) which tries to use the manipulators with
the Logger class, I get the following error messages:
g++ example2.cpp


example2.cpp: In function `int main()':
example2.cpp:51: error: no match for 'operator<<' in 'mainlog <<
std::setw(int)()'
example2.cpp:22: error: candidates are: Logger& Logger::operator<<(const
char*)
example2.cpp:28: error: Logger& Logger::operator<<(double)
example2.cpp:52: error: no match for 'operator<<' in '
(+(&mainlog)->Logger::operator<<(" x = "))->Logger::operator<<(x) <<
std::endl'
example2.cpp:22: error: candidates are: Logger& Logger::operator<<(const
char*)
example2.cpp:28: error: Logger& Logger::operator<<(double)
example2.cpp:53: error: `precision' undeclared (first use this function)
example2.cpp:53: error: (Each undeclared identifier is reported only once
for
each function it appears in.)
example2.cpp:54: error: no match for 'operator<<' in '
(&mainlog)->Logger::operator<<("x = ") << std::showpos'
example2.cpp:22: error: candidates are: Logger& Logger::operator<<(const
char*)
example2.cpp:28: error: Logger& Logger::operator<<(double)
Simplified example code:

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

using namespace std;

class Logger
{
public:
Logger(const char* filename = "program.log")
{
logfile = new fstream(filename, fstream::out);
}

~Logger()
{
logfile->close();
delete logfile;
}

Logger& operator<<(const char* msg)
{
*logfile << msg;
return *this;
}

Logger& operator<<(const double val)
{
*logfile << val;
return *this;
}

private:
fstream* logfile;
};

int main()
{
Logger mainlog;
double x = 12.34567;

// These work fine
cout << setw(20) << setfill('*') << setprecision(4);
cout << " x = " << x << endl;
cout.precision(2);
cout << "x = " << showpos << scientific << x << endl;

mainlog << "x = " << x << "\n";

// These don't work
//mainlog << setw(20) << setfill('*') << setprecision(4);
//mainlog << " x = " << x << endl;
//mainlog.precision(2);
//mainlog << "x = " << showpos << scientific << x << endl;

return 0;
}
------------------------------------

Any comments/suggestions are again very welcome!

Riku

--
life, space, irc

Oct 25 '05 #1
5 2158
Riku Jarvinen wrote:
Hi everyone,

I asked another question regarding this same subject about a week ago. See
thread:

http://groups.google.fi/group/comp.l...0bae667a479add
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 accept the iostream manipulators, including special
manipulators in <iomanip>. How can I make the logging class handle all the
manipulators in the same way std::cout does?

If I compile the code (see below) which tries to use the manipulators with [snip]

Simplified example code:

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

using namespace std;

class Logger
{
public:
Logger(const char* filename = "program.log")
{
logfile = new fstream(filename, fstream::out);
}

~Logger()
{
logfile->close();
delete logfile;
}

Logger& operator<<(const char* msg)
{
*logfile << msg;
return *this;
}

Logger& operator<<(const double val)
{
*logfile << val;
return *this;
}
what about replacing all these by a template:

template < typename T >
Logger& operator<< ( T const & t ) {
*logfile << val;
return *this;
}

This should handle the manipulators, too. (not tested!)

private:
fstream* logfile;
};

int main()
{
Logger mainlog;
double x = 12.34567;

// These work fine
cout << setw(20) << setfill('*') << setprecision(4);
cout << " x = " << x << endl;
cout.precision(2);
cout << "x = " << showpos << scientific << x << endl;

mainlog << "x = " << x << "\n";

// These don't work
//mainlog << setw(20) << setfill('*') << setprecision(4);
//mainlog << " x = " << x << endl;
//mainlog.precision(2);
//mainlog << "x = " << showpos << scientific << x << endl;

return 0;
}

Best

Kai-Uwe Bux

Oct 25 '05 #2
Kai-Uwe Bux wrote:

[code]

what about replacing all these by a template:

template < typename T >
Logger& operator<< ( T const & t ) {
*logfile << val;
return *this;
}

This should handle the manipulators, too. (not tested!)

I tried this typename template and it didn't seem to help in the manipulator
issue. I think I can add something like:

Logger& Logger::operator<<(ios_base& (*pf)(ios_base&))
{
*logfile << pf;
return *this;
}

but this works only with the manipulators in ios_base and, for example,
precision is a member function of ios_base, not a manipulator. Any thoughts?

Riku


Best

Kai-Uwe Bux


Oct 26 '05 #3
Riku Jarvinen wrote:
Kai-Uwe Bux wrote:

[code]

what about replacing all these by a template:

template < typename T >
Logger& operator<< ( T const & t ) {
*logfile << val;
return *this;
}

This should handle the manipulators, too. (not tested!)


I tried this typename template and it didn't seem to help in the
manipulator issue. I think I can add something like:


The only issue I see is the use of std::endl. Have a look at:
#include <iostream>
#include <fstream>
#include <iomanip>

using namespace std;

class Logger
{
public:
Logger(const char* filename = "program.log")
{
logfile = new fstream(filename, fstream::out);
}

~Logger()
{
logfile->close();
delete logfile;
}

template < typename T >
Logger& operator<<( T const & t )
{
*logfile << t;
return *this;
}

void precision ( unsigned long p ) {
*logfile << std::setprecision( p );
}

private:
fstream* logfile;
};

int main()
{
Logger mainlog;
double x = 12.34567;

// These work fine
cout << setw(20) << setfill('*') << setprecision(4);
cout << " x = " << x << endl;
cout.precision(2);
cout << "x = " << showpos << scientific << x << endl;

mainlog << "x = " << x << "\n";
mainlog << setw(20) << setfill('*') << setprecision(4);
mainlog << " x = " << x << '\n';
mainlog.precision(2);
mainlog << "x = " << showpos << scientific;
mainlog << x << '\n';

return 0;
}

Logger& Logger::operator<<(ios_base& (*pf)(ios_base&))
{
*logfile << pf;
return *this;
}

but this works only with the manipulators in ios_base and, for example,
precision is a member function of ios_base, not a manipulator. Any
thoughts?


See above. However, I do not yet have an idea about how to deal with endl.

Best

Kai-Uwe Bux
Oct 26 '05 #4
Kai-Uwe Bux wrote:
Riku Jarvinen wrote:

I tried this typename template and it didn't seem to help in the
manipulator issue. I think I can add something like:
The only issue I see is the use of std::endl. Have a look at:


Ok, thanks!

I think I have to include separately every member function of std::ostream,
std::ios and std::ios_base in the Logger class if I want to make it exactly
like std::cout?

However, I do not yet have an idea about how to deal with endl.

Actually, this (and all the other basic operator<< manipulators) can be
handled with the following addition to the class:

Logger& Logger::operator<<(ostream& (*pf)(ostream&))
{
*logfile << pf;
return *this;
}
Riku


#include <iostream>
#include <fstream>
#include <iomanip>

using namespace std;

class Logger
{
public:
Logger(const char* filename = "program.log")
{
logfile = new fstream(filename, fstream::out);
}

~Logger()
{
logfile->close();
delete logfile;
}

template < typename T >
Logger& operator<<( T const & t )
{
*logfile << t;
return *this;
}

void precision ( unsigned long p ) {
*logfile << std::setprecision( p );
}

private:
fstream* logfile;
};

int main()
{
Logger mainlog;
double x = 12.34567;

// These work fine
cout << setw(20) << setfill('*') << setprecision(4);
cout << " x = " << x << endl;
cout.precision(2);
cout << "x = " << showpos << scientific << x << endl;

mainlog << "x = " << x << "\n";
mainlog << setw(20) << setfill('*') << setprecision(4);
mainlog << " x = " << x << '\n';
mainlog.precision(2);
mainlog << "x = " << showpos << scientific;
mainlog << x << '\n';

return 0;
}

Logger& Logger::operator<<(ios_base& (*pf)(ios_base&))
{
*logfile << pf;
return *this;
}

but this works only with the manipulators in ios_base and, for example,
precision is a member function of ios_base, not a manipulator. Any
thoughts?


See above. However, I do not yet have an idea about how to deal with endl.

Best

Kai-Uwe Bux


Oct 26 '05 #5
Hi!

Riku Jarvinen schrieb:
[...]

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.).
[...]

Any comments/suggestions are again very welcome!


You could implement a streambuf derived class and and build an ostream
class with it. This ostream then can be used like any other ostream (I
implemented a iostream wrapper for bzip2 library this way).

Thomas
Oct 26 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Luis | last post by:
Below is my project. My Code is done, but when I try to compile it, my IDE crahses (again). I fixed up all the things you guys said I should, except for some which would not meet the project...
1
by: Sean W. Quinn | last post by:
Hey folks, I have a question regarding file handling, and the preservation of class structure. I have a class (and I will post snippets of code later in the post) with both primitive data...
6
by: Chris Mantoulidis | last post by:
Forgive me if I'm wrong but I think there is something like an extra member scope in classes. for example: class abc { ostream & operator << (ostream &, const abc &); istream & operator >>...
4
by: masood.iqbal | last post by:
Please help me with this doubt that I have regarding overloaded operators. Sometimes they are member functions and sometimes they are friends (e.g. see the code snippet from Stroustrup, Second...
7
by: Riku Jarvinen | last post by:
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...
13
by: olanglois | last post by:
Hi, I am trying to derive a new class that will add new functions but no new data members and the base class has overloaded operators (+,-,+=,-=,etc...) returning either (Base &) or (const Base)...
2
by: ZHENG Zhong | last post by:
Hi, I implemented a small logging library with the API like this: logger& log = log_manager::instance().get_logger("my_logger"); log.stream(DEBUG) << "this is a debug message" << std::endl;...
2
by: Angus | last post by:
I want to setup a macro to log informational strings if eg INFOLOGGING is defined. So I created a macro which outputs informational strings to a log file. I want to have a #define which...
2
by: Russell Warren | last post by:
I was just setting up some logging in a make script and decided to give the built-in logging module a go, but I just found out that the base StreamHandler always puts a newline at the end of each...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.