operator overloading - c++

How can I overload << operator (cout) so that it can be written to a file. Whenever << occurs it should be appended to the file i.e. instead of displaying on the screen it should be written to the file.
can i get a code for this...i am new to c++ and code written by me is not working..

Normally you provide std::ostream& operator<<(std::ostream&, const YourClass&) for your class and write to a file stream as follows:
std::ofstream ofs("out");
ofs << yourObject;
where yourObject is an object of YourClass.

Your overloaded << operator shouldn't care what kind of output stream that it goes to or whether it's appending or overwriting. It takes a std::ostream& and writes to it. If it's used with cout, then it's written to the console. If it's used with a std::ofstream, then it writes to a file. If that std::ofstream was opened to overwrite, then it overwrites. If it was opened to append, then it appends.
All that your overloaded << operator should care about is that it's writing to an output stream. What that stream represents is irrelevant.

This overloading is already done for the C++ file stream. The name cout means console out and the spirit is, it will output to console.
One thing you could do is use freopen(), to redirect all output to a file.

If you just want to send text to a file rather than the console, then std::ofstream is your friend. Like cout, your instance of ofstream shares the behaviour of ostream which already has a suitable << operator for strings and can be used exactly as cout. Here's an example:
#include <fstream>
int main()
{
std::ofstream fout("somefile.txt");
fout << "Some text" << std::endl;
return EXIT_SUCCESS;
}
Compile and run and you'll find that you have a new file in the current working directory:
% cat somefile.txt
Some text
If you need to stream an object that doesn't have operator << overloaded for std::ostream, then you you will need to overload the operator, like this:
std::ostream& operator <<(std::ostream& os, const SomeClass& instance)
{
instance.print(os);
return os;
}
You'll need void SomeClass::print(std::ostream& os) defined to send its private data to os (this saves you making the << a friend of your class).
Were you talking purely about cout, then this isn't "operator overloading", this is stream redirection. But, yes, it is possible (too) by setting the associated stream buffer using std::basic_ios::rdbuf().
Here is my solution from "Redirecting in C++":
#include <iostream>
#include <fstream>
class scoped_cout_redirector
{
public:
scoped_cout_redirector(const std::string& filename)
:backup_(std::cout.rdbuf())
,filestr_(filename.c_str())
,sbuf_(filestr_.rdbuf())
{
std::cout.rdbuf(sbuf_);
}
~scoped_cout_redirector()
{
std::cout.rdbuf(backup_);
}
private:
scoped_cout_redirector();
scoped_cout_redirector(const scoped_cout_redirector& copy);
scoped_cout_redirector& operator =(const scoped_cout_redirector& assign);
std::streambuf* backup_;
std::ofstream filestr_;
std::streambuf* sbuf_;
};
int main()
{
{
scoped_cout_redirector file1("file1.txt");
std::cout << "This is written to the first file." << std::endl;
}
std::cout << "This is written to stdout." << std::endl;
{
scoped_cout_redirector file2("file2.txt");
std::cout << "This is written to the second file." << std::endl;
}
return 0;
}

Related

How to redirect std::cout to file conditionally

In my code I have a a function that takes as argument a boolean variable. If this variable is true then the output shall be redirected to a file. If not, then to std::cout
The code looks like this and Its been inspired by a relevant question [1]
void MyClass::PPrint(bool ToFile)
{
std::streambuf *coutBufferBak = std::cout.rdbuf();
std::ofstream out("out.txt");
if (ToFile) { std::cout.rdbuf(out.rdbuf()); }
std::cout << "Will I be written to a file or to cout ?\n";
if (ToFile) {std::cout.rdbuf(coutBufferBak);} // reset cout
}
But in the case that the ToFile flag is false the file will be generated nonetheless and it will be empty. Is there a way to do it so that the file won't be generated ? If for example I try to include on the first IF statement the std::ofstream out("out.txt"); then I will get a SegFault due to the the variable scope being limited to that if.
Don't redirect std::cout. Write your print in terms of a std::ostream & parameter, and choose an appropriate std::ostream to pass.
void MyClass::PPrintImpl(std::ostream & out)
{
out << "Will I be written to a file or to cout ?\n";
}
// a.k.a
std::ostream & operator <<(std::ostream & out, const MyClass &)
{
return out << "Will I be written to a file or to cout ?\n";
}
void MyClass::PPrint(bool ToFile) {
if (ToFile) {
std::ofstream fout("out.txt");
PPrintImpl(fout);
} else {
PPrintImpl(std::cout);
}
}
We pass std::ostreams by reference because we the identity, not just the value of the stream object matters. We know this because they aren't copyable (the copy constructor is deleted)
You can open the file conditionally:
std::ofstream out;
if(...)
out.open("out.txt");

Obscure C++ operator overloading

I have the following code:
#include <iostream>
using namespace std;
ostream& f(ostream& os) {
return os << "hi";
}
int main() {
cout << "hello " << f << endl;
return 0;
}
And somehow this works - the output is "hello hi". How does this get interpreted by the compiler? I don't understand how a function can be inserted into a stream.
std::ostream has an operator<< overload that receives a pointer to a function with the signature such as the one you wrote (number 11 in this list):
basic_ostream& operator<<(
std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) );
which just calls the given function passing itself as argument. This overload (along with several similar others) is there to allow you to implement stream manipulators, i.e. stuff that you output in the stream with an << and changes the state of the stream from there. For example, our version of the (incorrectly) ubiquitous std::endl may be implemented as
std::ostream &myendl(std::ostream &s) {
s<<'\n';
s.flush();
return s;
}
which can then be used exactly as the "regular" std::endl:
std::cout<<"Hello, World!"<<myendl;
(the actual implementation is templated and a bit more complicated because it has to work even with wide streams, but you got the idea)
std::ostream::operator<< has an overload which accepts a function as parameter; and the body of that overload is to invoke the function given.
This is exactly how endl works in fact. endl is actually a function similar to:
ostream &endl(ostream &os)
{
os << '\n';
os.flush();
return os;
}

Custom class ostringstream output error

I don't know why this is erroring, but I'm just trying to add something "akin" to endl so that I can throw what's in an ostringstream to our debugger. I have the following:
class debug_stream_info
{
public:
debug_stream_info(int errorLine, char *errorFile, int level)
:m_errorLine(errorLine), m_errorFile(errorFile), m_logLevel(level)
{
}
friend std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info);
private:
int m_errorLine;
std::string m_errorFile;
int m_logLevel;
};
std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info)
{
// Write the stream's contents to cpu_debug
// Deleted custom logging function. No errors here though
// Clear the stream for re-use.
os.str("");
os.seekp(0);
return os;
}
int main(int argc, char** argv)
{
std::ostringstream myout;
myout << "hey there" << " and some more " << "Numbers!!: " << 435 << 54.2 << " that's good for numbers" << debug_stream_info(__LINE__, __FILE__, LOG_LEVEL);
return 0;
}
The error I'm getting is: error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'debug_stream_info' (or there is no acceptable conversion) for the line in main. This is on VS2008.
I'm including sstream, iostream, etc, and have the namespaces set up right. I'm getting no other errors. I even tried replacing all occurrances of basic_ostream with just ostringstream and there was no difference (I'll be having a w_char version later, but I wanted the simple case to work first). I made the object on the line above and then passed a fully-constructed object on the line, and the error was exactly the same. I've changed the signature of the second argument to and from const with no change as well.
Any ideas on what I'm doing wrong here?
Edit: since EVERY response seems to want to put it there, I can NOT use std::ostream because I want this to work ONLY for std::ostringstream (and std::basic_ostringstream) and not for any type of output stream. Besides, the function wouldn't compile with ostream anyways, since I'm using the os.str() method, which isn't in ostream, only the sub-classes.
The real problem with your code is that you've overloaded std::ostringstream rather than std::ostream. So your code would work if you write this:
debug_stream_info info(/** blah blah**/);
std::ostringstream oss;
oss << info ; //OK
However this will not work:
oss << 1 << info; //ERROR
This is compilation error because the expression oss<<1 returns an object of type std::ostream& which doesn't have overload which takes debug_stream_info as second argument. That means if you use cast as:
static_cast<std::ostringstream&>(oss << 1) << info; //OK
then that should work again.
So the solution is to overload std::ostream, instead of std::basic_ostringstream.
Also, the second parameter should be const & . This is also a problem with your code.
So write this:
std::ostream& operator<<(std::ostream&, debug_stream_info const &);
//^^^^^^^ note this
The second parameter should be const & so that you could write temporary objects to the stream.
debug_stream_info(__LINE__, __FILE__, LOG_LEVEL); is creating unnamed object which is not returning anything hence error
#include <iostream>
#include <cstdio>
#include <sstream>
using namespace std;
class debug_stream_info
{
public:
debug_stream_info(int errorLine, char *errorFile, int level)
:m_errorLine(errorLine), m_errorFile(errorFile), m_logLevel(level)
{
}
friend std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info);
std::ostringstream& fun(std::ostringstream& os)
{
os<<"Ashish"<<endl;
return os;
}
private:
int m_errorLine;
std::string m_errorFile;
int m_logLevel;
};
std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info)
{
// Write the stream's contents to cpu_debug
// Deleted custom logging function. No errors here though
// Clear the stream for re-use.
// os.str("");
// os.seekp(0);
return os;
}
int main(int argc, char** argv)
{
std::ostringstream myout, test;
myout << "hey there" << " and some more " << "Numbers!!: " << 435 << 54.2 << " that's good for numbers"
<< debug_stream_info(1, "/home/ashish/test", 1).fun(test);
return 0;
}
Nawaz has explained very clearly why you're getting the error. The
usual solution in this case is to define your own stream type, unrelated
to std::istream. Something along the lines of:
class DebugStream
{
std::ostringstring* collector;
public:
template <typename T>
DebugStream& operator<<( T const& value )
{
if ( collector != NULL ) {
*collector << value;
}
return *this;
}
};
There are infinite variations on this; in your case, you could add a
non-template member function for your type; more likely, you'd add a
constructor which took the same arguments:
DebugStream( int lineNumber, std::string const& filename, int logLevel )
: collector( isActive( logLevel ) ? new std::ostringstream : NULL )
{
// Initial insertion of lineNumber, filename, timestamp...
}
You can also add a destructor which atomically flushes the collected
data to a file (or sends an email, or writes it to the system log, or
whatever). (Be very careful about this. You don't want an exception to
escape from the destructor, even if the logging fails.)
Finally, you might want to use a custom streambuf, rather than
stringstream. Say one that keeps the allocated buffer from one
instance to the next. And if you do this, rather than newing the
stream each time, you might pick up an instance from a table, indexed by
the log level (and initialized from a configuration file).

is it possible to pass iostream into a function?

What I mean:
Everyone knows this method of redirecting stream to output:
cout << "sometext"
but is it possible to pass that stream to a function like this:
my_function() << "sometext";
Yes*:
#include <iostream>
#include <ostream>
std::ostream & my_function() { return std::cout; }
// ...
my_function() << "Hello world.\n";
*) Nothing you said in words is entirely correct, and you may well struggle later integrate this into your project, but this answer shows how to make your code do what you want.
Everyone knows this method of redirecting stream to output:
That's not what that does. The stream is called cout; that's the iostream object. The << operator does not redirect anything. The std::ostream objects all have overloaded operator<< functions. Those functions are invoked when you use << with a stream on the left-hand side and some type that has an overload for it on the right.
<< "sometext" is not a "stream" that can be "redirected". It isn't even a valid expression in C++. The << operator is binary. it takes two parameters.
my_function() << "sometext"; can only work if it returns a std::ostream class or something derived from it. Or something that has an overloaded operator<< defined for it and const char*.
cout << "sometext"
This is not "redirecting stream to output" it is invoking the operator << function on the cout object with the string literal "sometext"
if my_function() is returning a ostream which has operator << overloaded then my_function() << "sometext" will compile else it will give an error.
If you are looking for a way to overload << for your own function unrelated to streams, here is how you can do it:
struct MyStruct {
void DoSomething(const string& s);
};
MyStruct &operator<<(MyStruct &x, const string& s) {
x.DoSomething(s);
return x;
}
MyStruct& my_function() {
return MyStruct;
}
int main() {
my_function() << "Hello, world!";
}
In this example, DoSomething will be called on the instance of MyStruct returned from my_function, and "Hello, world!" will be passed to it as an argument.
If I understand what you are asking about, the closest equivalent of a shell redirect for a function that uses std::cout for output is probably to switch temporarily std::cout's internal stream buffer for a different one.
Of course, this is inherently not thread safe and won't cope if the function itself expects std::cout and stdout to be the same underlying thing.
#include <iostream>
#include <sstream>
int main()
{
std::stringbuf redir( std::ios_base::out );
std::streambuf* save = std::cout.rdbuf( &redir );
my_function(); // cout output ends up in redir
std::cout.rdbuf( save ); // restore original cout
}

Overload handling of std::endl?

I want to define a class MyStream so that:
MyStream myStream;
myStream << 1 << 2 << 3 << std::endl << 5 << 6 << std::endl << 7 << 8 << std::endl;
gives output
[blah]123
[blah]56
[blah]78
Basically, I want a "[blah]" inserted at the front, then inserted after every non terminating std::endl?
The difficulty here is NOT the logic management, but detecting and overloading the handling of std::endl. Is there an elegant way to do this?
Thanks!
EDIT: I don't need advice on logic management. I need to know how to detect/overload printing of std::endl.
What you need to do is write your own stream buffer: When the stream buffer is flushed you output you prefix characters and the content of the stream.
The following works because std::endl causes the following.
Add '\n' to the stream.
Calls flush() on the stream
This calls pubsync() on the stream buffer.
This calls the virtual method sync()
Override this virtual method to do the work you want.
#include <iostream>
#include <sstream>
class MyStream: public std::ostream
{
// Write a stream buffer that prefixes each line with Plop
class MyStreamBuf: public std::stringbuf
{
std::ostream& output;
public:
MyStreamBuf(std::ostream& str)
:output(str)
{}
~MyStreamBuf() {
if (pbase() != pptr()) {
putOutput();
}
}
// When we sync the stream with the output.
// 1) Output Plop then the buffer
// 2) Reset the buffer
// 3) flush the actual output stream we are using.
virtual int sync() {
putOutput();
return 0;
}
void putOutput() {
// Called by destructor.
// destructor can not call virtual methods.
output << "[blah]" << str();
str("");
output.flush();
}
};
// My Stream just uses a version of my special buffer
MyStreamBuf buffer;
public:
MyStream(std::ostream& str)
:std::ostream(&buffer)
,buffer(str)
{
}
};
int main()
{
MyStream myStream(std::cout);
myStream << 1 << 2 << 3 << std::endl << 5 << 6 << std::endl << 7 << 8 << std::endl;
}
> ./a.out
[blah]123
[blah]56
[blah]78
>
Your overloaded operators of the MyStream class have to set a previous-printed-token-was-endl flag.
Then, if the next object is printed, the [blah] can be inserted in front of it.
std::endl is a function taking and returning a reference to std::ostream. To detect it was shifted into your stream, you have to overload the operator<< between your type and such a function:
MyStream& operator<<( std::ostream&(*f)(std::ostream&) )
{
std::cout << f;
if( f == std::endl )
{
_lastTokenWasEndl = true;
}
return *this;
}
Agreed with Neil on principle.
You want to change the behavior of the buffer, because that is the only way to extend iostreams. endl does this:
flush(__os.put(__os.widen('\n')));
widen returns a single character, so you can't put your string in there. put calls putc which is not a virtual function and only occasionally hooks to overflow. You can intercept at flush, which calls the buffer's sync. You would need to intercept and change all newline characters as they are overflowed or manually synced and convert them to your string.
Designing an override buffer class is troublesome because basic_streambuf expects direct access to its buffer memory. This prevents you from easily passing I/O requests to a preexisting basic_streambuf. You need to go out on a limb and suppose you know the stream buffer class, and derive from it. (cin and cout are not guaranteed to use basic_filebuf, far as I can tell.) Then, just add virtual overflow and sync. (See ยง27.5.2.4.5/3 and 27.5.2.4.2/7.) Performing the substitution may require additional space so be careful to allocate that ahead of time.
- OR -
Just declare a new endl in your own namespace, or better, a manipulator which isn't called endl at all!
I use function pointers. It sounds terrifying to people who aren't used to C, but it's a lot more efficient in most cases. Here's an example:
#include <iostream>
class Foo
{
public:
Foo& operator<<(const char* str) { std::cout << str; return *this; }
// If your compiler allows it, you can omit the "fun" from *fun below. It'll make it an anonymous parameter, though...
Foo& operator<<(std::ostream& (*fun)(std::ostream&)) { std::cout << std::endl; }
} foo;
int main(int argc,char **argv)
{
foo << "This is a test!" << std::endl;
return 0;
}
If you really want to you can check for the address of endl to confirm that you aren't getting some OTHER void/void function, but I don't think it's worth it in most cases. I hope that helps.
Instead of attempting to modify the behavior of std::endl, you should probably create a filtering streambuf to do the job. James Kanze has an example showing how to insert a timestamp at the beginning of each output line. It should require only minor modification to change that to whatever prefix you want on each line.
I had the same question, and I thought that Potatoswatter's second answer had merit: "Just declare a new endl in your own namespace, or better, a manipulator which isn't called endl at all!"
So I found out how to write a custom manipulator which is not hard at all:
#include <sstream>
#include <iostream>
class log_t : public std::ostringstream
{
public:
};
std::ostream& custom_endl(std::ostream& out)
{
log_t *log = dynamic_cast<log_t*>(&out);
if (log)
{
std::cout << "custom endl succeeded.\n";
}
out << std::endl;
return out;
}
std::ostream& custom_flush(std::ostream& out)
{
log_t *log = dynamic_cast<log_t*>(&out);
if (log)
{
std::cout << "custom flush succeeded.\n";
}
out << std::flush;
return out;
}
int main(int argc, char **argv)
{
log_t log;
log << "custom endl test" << custom_endl;
log << "custom flush test" << custom_flush;
std::cout << "Contents of log:\n" << log.str() << std::endl;
}
Here's the output:
custom endl succeeded.
custom flush succeeded.
Contents of log:
custom endl test
custom flush test
Here I've created two custom manipulators, one that handles endl and one that handles flush. You can add whatever processing you want to these two functions, since you have a pointer to the log_t object.
You can't change std::endl - as it's name suggests it is a part of the C++ Standard Library and its behaviour is fixed. You need to change the behaviour of the stream itself, when it receives an end of line . Personally, I would not have thought this worth the effort, but if you want to venture into this area I strongly recommend reading the book Standard C++ IOStreams & Locales.