Hello, I have a class that I want to be able to output detailed information
about what it's doing either
to a file or to the screen. What I first tried was adding a
std::ostream-reference member variable to
the class and then adding a constructor that, apart from the "normal"
arguments, also took an std::ostream&.
I then intended to set a boolean member variable called logging to true and
have the other member functions
check that variable to determine whether they should perform logging or not.
Something like:
class foo
{
public:
foo(args); /* logging set to false, m_out set to nothing */
foo(args, std::ostream& out); /* logging set to true, m_out set to out */
void bar(); /* log to m_out if logging == true */
private:
std::ostream& m_out;
bool logging;
};
I thought about what would happen if I in a member function forgot to check
the value of logging and tried
to use m_out without it referencing something. However, I didn't get that
far because the compiler stopped
me saying that I must initialize m_out (which I didn't do in the first
constructor).
I understand why...there is no such thing as a NULL reference, it has to be
a reference to a valid object
and it may never be set to reference something else.
So I was thinking having the second constructor accepting a const
std::string& instead and that string would
hold a file name and then I would open a file with that name and log to it.
But that variant isn't very
satisfying because then the user wont be able to log directly to cout or
cerr...how do I proceed? I could solve
it by using the preprocessor...#ifndef LOGGING, and that would probably
yield faster code for the times
when I dont want logging turned on because I never would have to check any
flags or something (and yield
a smaller program), but it's not very flexible.
/ Eric 19 1460
Eric Lila wrote: Hello, I have a class that I want to be able to output detailed information about what it's doing either to a file or to the screen. What I first tried was adding a std::ostream-reference member variable to the class and then adding a constructor that, apart from the "normal" arguments, also took an std::ostream&. I then intended to set a boolean member variable called logging to true and have the other member functions check that variable to determine whether they should perform logging or not. Something like:
class foo { public: foo(args); /* logging set to false, m_out set to nothing */ foo(args, std::ostream& out); /* logging set to true, m_out set to out */
void bar(); /* log to m_out if logging == true */
private: std::ostream& m_out; bool logging; };
I thought about what would happen if I in a member function forgot to check the value of logging and tried to use m_out without it referencing something. However, I didn't get that far because the compiler stopped me saying that I must initialize m_out (which I didn't do in the first constructor). I understand why...there is no such thing as a NULL reference, it has to be a reference to a valid object and it may never be set to reference something else. So I was thinking having the second constructor accepting a const std::string& instead and that string would hold a file name and then I would open a file with that name and log to it. But that variant isn't very satisfying because then the user wont be able to log directly to cout or cerr...how do I proceed? I could solve it by using the preprocessor...#ifndef LOGGING, and that would probably yield faster code for the times when I dont want logging turned on because I never would have to check any flags or something (and yield a smaller program), but it's not very flexible.
I would give 'out' a default value, which is, say, a static member of
your 'foo' class, and is essentially a /dev/null kind of stream:
class foo {
foo(args, std::ostream &s = foo::nullstream);
static std::ostream& nullstream;
};
std::ostream& foo::nullstream = ??? ;
You would have to find a decent implementation of the nullstream (I am
not that good with streams to give you a one-liner for it). All you
need is a stream whose buffer would just eat all and do nothing. I bet
there are implementations of it out there.
V
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:Kg*****************@newsread1.dllstx09.us.to. verio.net... Eric Lila wrote: Hello, I have a class that I want to be able to output detailed information about what it's doing either to a file or to the screen. What I first tried was adding a std::ostream-reference member variable to the class and then adding a constructor that, apart from the "normal" arguments, also took an std::ostream&. I then intended to set a boolean member variable called logging to true and have the other member functions check that variable to determine whether they should perform logging or not. Something like:
class foo { public: foo(args); /* logging set to false, m_out set to nothing */ foo(args, std::ostream& out); /* logging set to true, m_out set to out */
void bar(); /* log to m_out if logging == true */
private: std::ostream& m_out; bool logging; };
I thought about what would happen if I in a member function forgot to check the value of logging and tried to use m_out without it referencing something. However, I didn't get that far because the compiler stopped me saying that I must initialize m_out (which I didn't do in the first constructor). I understand why...there is no such thing as a NULL reference, it has to be a reference to a valid object and it may never be set to reference something else. So I was thinking having the second constructor accepting a const std::string& instead and that string would hold a file name and then I would open a file with that name and log to it. But that variant isn't very satisfying because then the user wont be able to log directly to cout or cerr...how do I proceed? I could solve it by using the preprocessor...#ifndef LOGGING, and that would probably yield faster code for the times when I dont want logging turned on because I never would have to check any flags or something (and yield a smaller program), but it's not very flexible.
I would give 'out' a default value, which is, say, a static member of your 'foo' class, and is essentially a /dev/null kind of stream:
class foo { foo(args, std::ostream &s = foo::nullstream); static std::ostream& nullstream; };
std::ostream& foo::nullstream = ??? ;
You would have to find a decent implementation of the nullstream (I am not that good with streams to give you a one-liner for it). All you need is a stream whose buffer would just eat all and do nothing. I bet there are implementations of it out there.
V
That seems to be a nice solution! I am googling right now to see what I
can find, no luck yet though. Lots of hits, just not found what I'm looking
for yet.
Thanks Victor
/ Eric
Eric Lilja wrote: private: std::ostream& m_out; bool logging; };
One option to your problem would be to add a null output
device.
class NullStreamBuf : public streambuf {
int_type overflow(int_type c) { return c; }
} ;
class NullStream : public ostream
public:
NullStream() : ostream(new NullStreamBuf) { }
~NullStream() { delete rdbuf(); }
};
You can then output to the stream to your heart's content
and the data is just discarded.
Eric Lilja wrote: [...] I am googling right now to see what I can find, no luck yet though. Lots of hits, just not found what I'm looking for yet.
See Ron's post.
Eric Lilja wrote: Hello, I have a class that I want to be able to output detailed information about what it's doing either to a file or to the screen. What I first tried was adding a std::ostream-reference member variable to the class and then adding a constructor that, apart from the "normal" arguments, also took an std::ostream&. I then intended to set a boolean member variable called logging to true and have the other member functions check that variable to determine whether they should perform logging or not. Something like:
class foo { public: foo(args); /* logging set to false, m_out set to nothing */ foo(args, std::ostream& out); /* logging set to true, m_out set to out */
void bar(); /* log to m_out if logging == true */
private: std::ostream& m_out; bool logging; };
I thought about what would happen if I in a member function forgot to check the value of logging and tried to use m_out without it referencing something. However, I didn't get that far because the compiler stopped me saying that I must initialize m_out (which I didn't do in the first constructor). I understand why...there is no such thing as a NULL reference, it has to be a reference to a valid object and it may never be set to reference something else. So I was thinking having the second constructor accepting a const std::string& instead and that string would hold a file name and then I would open a file with that name and log to it. But that variant isn't very satisfying because then the user wont be able to log directly to cout or cerr...how do I proceed? I could solve it by using the preprocessor...#ifndef LOGGING, and that would probably yield faster code for the times when I dont want logging turned on because I never would have to check any flags or something (and yield a smaller program), but it's not very flexible.
/ Eric
You can use something like this:
#include <iostream>
class Logger {
public:
Logger() : stream(0) {}
Logger( std::ostream &out ) { enable( out ); }
template <class T>
Logger &operator<<(T t) { if( stream ) *stream << t; return *this; }
Logger &operator<<( std::ostream&(*manip)(std::ostream&) ) { if(
stream ) *stream << manip; return *this; }
void enable( std::ostream &out ) { stream = &out; }
void disable() { stream = 0; }
private:
std::ostream *stream;
};
int main()
{
Logger log( std::cout );
log << "hello world" << std::endl;
log.disable();
log << "hello world again" << std::endl;
return 0;
}
So just create an instance of Logger as member in your class and use it
for logging in methods.
--
Regards,
Slava
Eric Lilja wrote: Hello, I have a class that I want to be able to output detailed information about what it's doing either to a file or to the screen. What I first tried was adding a std::ostream-reference member variable to the class and then adding a constructor that, apart from the "normal" arguments, also took an std::ostream&. I then intended to set a boolean member variable called logging to true and have the other member functions check that variable to determine whether they should perform logging or not. Something like:
class foo { public: foo(args); /* logging set to false, m_out set to nothing */ foo(args, std::ostream& out); /* logging set to true, m_out set to out */
void bar(); /* log to m_out if logging == true */
private: std::ostream& m_out; bool logging; };
I thought about what would happen if I in a member function forgot to check the value of logging and tried to use m_out without it referencing something. However, I didn't get that far because the compiler stopped me saying that I must initialize m_out (which I didn't do in the first constructor). I understand why...there is no such thing as a NULL reference, it has to be a reference to a valid object and it may never be set to reference something else. So I was thinking having the second constructor accepting a const std::string& instead and that string would hold a file name and then I would open a file with that name and log to it. But that variant isn't very satisfying because then the user wont be able to log directly to cout or cerr...how do I proceed? I could solve it by using the preprocessor...#ifndef LOGGING, and that would probably yield faster code for the times when I dont want logging turned on because I never would have to check any flags or something (and yield a smaller program), but it's not very flexible.
/ Eric
You can use something like this:
#include <iostream>
class Logger {
public:
Logger() : stream(0) {}
Logger( std::ostream &out ) { enable( out ); }
template <class T>
Logger &operator<<(T t) { if( stream ) *stream << t; return *this; }
Logger &operator<<( std::ostream&(*manip)(std::ostream&) ) { if(
stream ) *stream << manip; return *this; }
void enable( std::ostream &out ) { stream = &out; }
void disable() { stream = 0; }
private:
std::ostream *stream;
};
int main()
{
Logger log( std::cout );
log << "hello world" << std::endl;
log.disable();
log << "hello world again" << std::endl;
return 0;
}
So just create an instance of Logger as member in your class and use it
for logging in methods.
--
Regards,
Slava
"Ron Natalie" wrote: Eric Lilja wrote:
private: std::ostream& m_out; bool logging; }; One option to your problem would be to add a null output device.
class NullStreamBuf : public streambuf { int_type overflow(int_type c) { return c; }
} ;
class NullStream : public ostream public: NullStream() : ostream(new NullStreamBuf) { } ~NullStream() { delete rdbuf(); }
};
You can then output to the stream to your heart's content and the data is just discarded.
Thanks Ron, your version was a bit simpler than the one I found at http://www.msobczak.com/prog/downloads.html (nullstream).
My constructor now takes a std::ostream& as its last argument and that
argument
has a default value:
foo(args, std::ostream& out = foo::nullstream);
where nullstream is a static data member of foo defined as:
std::ostream& LinearHashTable::nullstream = *( new NullStream());
The fact that I am using new is a bit troubling but then again, I cannot
reference a temporary. I guess I don't have to worry about deleting it,
because
it will be destroyed when the program exits and then all memory is returned
to OS, right?
Now I wonder if should check if out is actually a NullStream (and how would
I do that?) or not and set
the logging member variable accordingly or just skip that and always write
to
the stream (thinking about performance here).
/ Eric
Vyacheslav Kononenko wrote: class Logger { public: Logger() : stream(0) {}
.... int main() { Logger log( std::cout );
log << "hello world" << std::endl; log.disable(); log << "hello world again" << std::endl;
return 0; }
So just create an instance of Logger as member in your class and use it for logging in methods.
I don't suppose you actually tried the above. It isn't going
to work. Logger isn't derived from ostream, those endls aren't
going to work and you'll end up with other issues.
"Eric Lilja" <er*******************@yahoo.com> wrote in message
news:cn**********@news.island.liu.se... "Ron Natalie" wrote: Eric Lilja wrote:
private: std::ostream& m_out; bool logging; }; One option to your problem would be to add a null output device.
class NullStreamBuf : public streambuf { int_type overflow(int_type c) { return c; }
} ;
class NullStream : public ostream public: NullStream() : ostream(new NullStreamBuf) { } ~NullStream() { delete rdbuf(); }
};
You can then output to the stream to your heart's content and the data is just discarded.
Thanks Ron, your version was a bit simpler than the one I found at http://www.msobczak.com/prog/downloads.html (nullstream).
My constructor now takes a std::ostream& as its last argument and that argument has a default value: foo(args, std::ostream& out = foo::nullstream); where nullstream is a static data member of foo defined as: std::ostream& LinearHashTable::nullstream = *( new NullStream()); The fact that I am using new is a bit troubling but then again, I cannot reference a temporary. I guess I don't have to worry about deleting it, because it will be destroyed when the program exits and then all memory is returned to OS, right?
Now I wonder if should check if out is actually a NullStream (and how would I do that?) or not and set the logging member variable accordingly or just skip that and always write to the stream (thinking about performance here).
I am testing if the std::ostream reference passed to the constructor is in
fact
a nullstream by performing a dynamic_cast. If the cast returns NULL, I set
logging to true.
/ Eric
/ Eric
Ron Natalie wrote in news:41***********************@news.newshosting.co m in
comp.lang.c++: So just create an instance of Logger as member in your class and use it for logging in methods. I don't suppose you actually tried the above.
Worked for me.
It isn't going to work. Logger isn't derived from ostream, those endls aren't going to work and you'll end up with other issues.
Such as?
Rob.
-- http://www.victim-prime.dsl.pipex.com/
"Eric Lilja" <er*******************@yahoo.com> wrote... [...] I am testing if the std::ostream reference passed to the constructor is in fact a nullstream by performing a dynamic_cast. If the cast returns NULL, I set logging to true.
Actually comparing addresses would be simpler, I believe:
foo(blah, std::ostream& s)
: m_out(s), logging(&s != &foo::nullstream) {}
V
Eric Lilja wrote: Now I wonder if should check if out is actually a NullStream (and how would I do that?) or not and set the logging member variable accordingly or just skip that and always write to the stream (thinking about performance here).
I am testing if the std::ostream reference passed to the constructor is in fact a nullstream by performing a dynamic_cast. If the cast returns NULL, I set logging to true.
If you're willing to put an if statement around every logging statement,
there's no point using a null_stream at all. You can just change the
reference to a pointer in your original class:
#include <ostream>
struct args { };
class foo
{
public:
foo (args) : m_out (0) { }
foo (args, std::ostream & out) : m_out (& out) { }
void bar ()
{
if (m_out)
{
(* m_out) << "Barring." << std::endl;
}
}
private:
std::ostream * m_out;
};
The gain in readability is small. How about something a little dirtier
for maximum performance:
#ifdef NDEBUG
#define IFDEBUG(a) 0
#else
#define IFDEBUG(a) a
#endif
#endif
#include <iostream>
#include <ostream>
int main ()
{
IFDEBUG ((std::cout << "Logging." << std::endl));
}
While using a nullstream sure provide a more elegant solution(Since it
cleans up the logging code), a simpler approach would simply have been to
switch from references to pointers, since pointers can indeed be null.
-Eric Fournier
"Eric Lilja" <er*******************@yahoo.com> a écrit dans le message de
news:cn**********@news.island.liu.se... Hello, I have a class that I want to be able to output detailed
information about what it's doing either to a file or to the screen. What I first tried was adding a std::ostream-reference member variable to the class and then adding a constructor that, apart from the "normal" arguments, also took an std::ostream&. I then intended to set a boolean member variable called logging to true
and have the other member functions check that variable to determine whether they should perform logging or
not. Something like:
class foo { public: foo(args); /* logging set to false, m_out set to nothing */ foo(args, std::ostream& out); /* logging set to true, m_out set to out
*/ void bar(); /* log to m_out if logging == true */
private: std::ostream& m_out; bool logging; };
I thought about what would happen if I in a member function forgot to
check the value of logging and tried to use m_out without it referencing something. However, I didn't get that far because the compiler stopped me saying that I must initialize m_out (which I didn't do in the first constructor). I understand why...there is no such thing as a NULL reference, it has to
be a reference to a valid object and it may never be set to reference something else. So I was thinking having the second constructor accepting a const std::string& instead and that string would hold a file name and then I would open a file with that name and log to
it. But that variant isn't very satisfying because then the user wont be able to log directly to cout or cerr...how do I proceed? I could solve it by using the preprocessor...#ifndef LOGGING, and that would probably yield faster code for the times when I dont want logging turned on because I never would have to check any flags or something (and yield a smaller program), but it's not very flexible.
/ Eric
> My constructor now takes a std::ostream& as its last argument and that argument has a default value: foo(args, std::ostream& out = foo::nullstream); where nullstream is a static data member of foo defined as: std::ostream& LinearHashTable::nullstream = *( new NullStream()); The fact that I am using new is a bit troubling but then again, I cannot reference a temporary. I guess I don't have to worry about deleting it, because it will be destroyed when the program exits and then all memory is returned to OS, right?
No need for new. Just make nullstream an object not a reference
NullStream LinearHashTable::nullstream;
john
"John Harrison" <jo*************@hotmail.com> wrote in message
news:2v*************@uni-berlin.de... My constructor now takes a std::ostream& as its last argument and that argument has a default value: foo(args, std::ostream& out = foo::nullstream); where nullstream is a static data member of foo defined as: std::ostream& LinearHashTable::nullstream = *( new NullStream()); The fact that I am using new is a bit troubling but then again, I cannot reference a temporary. I guess I don't have to worry about deleting it, because it will be destroyed when the program exits and then all memory is returned to OS, right?
No need for new. Just make nullstream an object not a reference
NullStream LinearHashTable::nullstream;
john
Thanks John, I've changed the type of the static data member nullstream from
std::ostream& to just NullStream.
When I first tried to define it I wrote NullStream
LinearHashTable::nullstream = NullStream();
I didn't realise that that code tried to use the copy constructor (which, as
you know, is private for ostreams), I changed to
your variant which invokes the default constructor.
/ Eric
Eric Lilja wrote: Now I wonder if should check if out is actually a NullStream (and how would I do that?) or not and set the logging member variable accordingly or just skip that and always write to the stream (thinking about performance here).
Look at my solution there is no such problem there. / Eric
--
Regards,
Slava
Ron Natalie wrote: Vyacheslav Kononenko wrote:
class Logger { public: Logger() : stream(0) {}
...
int main() { Logger log( std::cout );
log << "hello world" << std::endl; log.disable(); log << "hello world again" << std::endl;
return 0; }
So just create an instance of Logger as member in your class and use it for logging in methods.
I don't suppose you actually tried the above. It isn't going to work. Logger isn't derived from ostream, those endls aren't going to work and you'll end up with other issues.
You are wrong. You just did not pay attention to this:
Logger &operator<<( std::ostream&(*manip)(std::ostream&) ) { if( stream
) *stream << manip; return *this; }
What are other issues?
--
Regards,
Slava
"Vyacheslav Kononenko" <vy********@NOkononenkoSPAM.net> wrote in message
news:%i*****************@mencken.net.nih.gov... Eric Lilja wrote:
Now I wonder if should check if out is actually a NullStream (and how would I do that?) or not and set the logging member variable accordingly or just skip that and always write to the stream (thinking about performance here).
Look at my solution there is no such problem there. / Eric
-- Regards, Slava
I will, thanks for your help, Slava. I'm always interested in different
approaches to problems. Even if I choose one
over the other this time it might be the other way around next time.
/ Eric You are wrong. You just did not pay attention to this: Logger &operator<<( std::ostream&(*manip)(std::ostream&) ) { if( stream ) *stream << manip; return *this; }
Sorry, you are right. What are other issues
It means you can't use this stream with things expecting
ostream. If your entire world is limitted to operator<<
that's fine. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Dan Perl |
last post by:
There is something with initializing mutable class attributes that I am
struggling with. I'll use an example to explain:
class Father:
attr1=None # this is OK
attr2= # this is wrong
def foo(self, data):
self.attr1=data
self.attr2.append(data)
The initialization of attr1 is obviously OK, all instances of Father
redefine it in the...
|
by: Srini |
last post by:
Hello,
Rules for inline functions say that they have to be defined in the same
compilation unit as their declarations. For class member functions this
means that the inline member functions must be defined either within
the class or within the same header file.
But its generally a good programming practice to have the declarations
and...
|
by: David Lozzi |
last post by:
Howdy,
I've discovered how to create and use a class in ASP.NET. However, when is the best time to use a class? For example, I am currently using session variables to store user information (user id, user name, full name, security level, department, etc.). Would I do better to create a class instead? Also, if I did, would I simply store the ID...
|
by: Scott M. |
last post by:
What are the advantages of defining a class as part of another class
definition (nesting classes)?
|
by: thomasp |
last post by:
I have written my first Class and am posting it to this newsgroup with hopes
that I can get some feedback on what is right and what is wrong with it.
All comments are welcome, but more interested in what would make it better.
If I have totally missed on what a class is used for please inform me.
Thanks,
Thomas
| |
by: James |
last post by:
Many classes vs Many methods in a single class, which is a better way to
structure applications?
Regards
James
|
by: WXS |
last post by:
Vote for this idea if you like it here:
http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=5fee280d-085e-4fe2-af35-254fbbe96ee9
-----------------------------------------------------------------------------
This is a consortium of ideas from another thread on topic...
|
by: indy2718 |
last post by:
Hi,
I've been doing a reoccuring programming error. I'm using a Guard
class (like as in a mutex guard).
The Guard is doing a glBindTexture(new texture) in the constructor,
and then a unbinding BindTexture (original texture) in the
destructor. (see code at the end of this message).
Example:
{
|
by: George2 |
last post by:
Hello everyone,
I am feeling template function is more tricky than template class. For
the reason that the compiler will do the matching automatically for
template function, but for template class, developer can assign how to
match.
Sometimes compiler is doing mysterious matching rules for template
function, which makes us confused....
|
by: Phlip |
last post by:
1230987za wrote:
Kanze is a classically-trained "unit tester". In some circles "unit" is a QA
concept - specifically, if a test fails, you only need to inspect one unit.
So "units" are "things which are clearly delimited and accessible to
inspection". That should map onto C++ classes - specifically due to
overlapping requirements. C++...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language...
| |
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it. ...
|
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules.
He will explain when you may want to use classes...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
| |
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 we have to send another system
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |