function to format message & output to cerr/cout/ostream

T

Trevor

Hello,

Please bear with me, I am trying to learn C++. I am implementing some
error/debug functions which format a message and output it to a C++ stream.
I would like to design it using one low level function which accepts a
"generic C++ stream" as an argument (cerr, cout, ofstream, etc). I have
tried to make the parameter a const ostream&, but when I plug in cerr or
cout I get a compiler error. What am I doing wrong?

// The low level function just formats some message and outputs it to
"stream".
void _output(const ostream& stream, const char* reason, int error)
{
ostringstream message;
// ... do some formatting
if (stream == cerr)
cerr << message << endl;
else if (stream == cout)
cout << message << endl;
}

// the high level functions just direct the output to a different stream
void outputerr(const char* reason, int error)
{
// do something special for errors
_output(cerr, reason, error);
}

void outputcmt(const char* reason, int error)
{
// do something special for comments
_output(cout, reason, error);
}

void outputwrn(const char* reason, int error)
{
// do something special for warnings
_output(cout, reason, error);
}

The compiler error is:

binary '<<': no operator found which takes a left-hand operand of type
'const std::eek:stream' (or there is no acceptable conversion)

on the line of code:

"stream << message.str().c_str() << endl" // compiler error is in _output()
 
R

Rolf Magnus

Trevor said:
Hello,

Please bear with me, I am trying to learn C++. I am implementing
some
error/debug functions which format a message and output it to a C++
stream. I would like to design it using one low level function which
accepts a
"generic C++ stream" as an argument (cerr, cout, ofstream, etc). I
have tried to make the parameter a const ostream&, but when I plug in
cerr or
cout I get a compiler error. What am I doing wrong?

// The low level function just formats some message and outputs it to
"stream".
void _output(const ostream& stream, const char* reason, int error)
^^^^^
Your stream is const, so you cannot write to it.

{
ostringstream message;
// ... do some formatting
if (stream == cerr)
cerr << message << endl;
else if (stream == cout)
cout << message << endl;
}

// the high level functions just direct the output to a different
stream void outputerr(const char* reason, int error)
{
// do something special for errors
_output(cerr, reason, error);
}

void outputcmt(const char* reason, int error)
{
// do something special for comments
_output(cout, reason, error);
}

void outputwrn(const char* reason, int error)
{
// do something special for warnings
_output(cout, reason, error);
}

The compiler error is:

binary '<<': no operator found which takes a left-hand operand of type
'const std::eek:stream' (or there is no acceptable conversion)

Right. The operator takes an std::eek:stream&, not a const std::eek:stream&.
 
J

Jeff

Hi Trevor

Your code is fine, just remove the "const" before the ostream& in
_output() (there's no need for the stream to be const, and I'm not
sure of the internal workings of the << operator, so it might be
required to not be const... ):

=================================================

#include <iostream>
#include <sstream>
using namespace std;

// The low level function just formats some message and outputs it to
// "stream".
void _output(ostream& stream, const char* reason, int error)
{
ostringstream message;
// might need a big if/else if/else if to handle formatting for
each stream
message << "Here's generic formatting : " << reason << " ... :)
....";

// this code is just the same as that which follows
// ... do some formatting
// if (stream == cerr)
// cerr << message.str() << endl; // did you forget the str()
here?
// else if (stream == cout)
// cout << message.str() << endl; // ditto?

// assuming you just meant this?
stream << message.str() << endl; // .c_str() not required

}


// the high level functions just direct the output to a different
stream
// functions are as you showed them


int main() {
outputerr("error here", 2);
outputcmt("comment", 3);

return 0;
}

========================================================

Just a few quick notes, though:

1. Try to stay away from starting variable and function names with an
underscore, I don't think this is good style

2. If you're using the outputXXX (eg outputerr, outputcmt) functions
in your code, forwarding all of those function calls to another
routine (_output(), in this case), and then doing all the actual work
in the called routine /might/ not be a good choice, especially if you
have extensive checks and branches within the worker function (e.g.,
if (stream == std::cout) {} else if (stream == std::cerr) {} ... etc
....) Why not just do all the formatting etc in the original function
(outputerr, outputcmt ...)? Mind you, I don't know your design
choices, so you may have good reasons for this.

Good luck! Jeff
 

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

Forum statistics

Threads
473,744
Messages
2,569,480
Members
44,900
Latest member
Nell636132

Latest Threads

Top