I'm trying to create a report/logger Class in c++.
I want to have in the main an object called Report and apply to this class the operator << to write to file multiple strings just like ofstream does.
So instead of using the following code:
ofstream myfile ("d://example.txt");
if (myfile.is_open())
{
myfile << "This is a line.\n" << "Heya!!!" << endl;
myfile.close();
}
I would like to have something like the following :
Report rLogger ("d://example.txt"); // Report C'tor (const string& s)
logger << "This is a line.\n" << "Heya!!!" << endl;
// the destructor of rLogger will close the file when it dies...
I just can't find out a way to write the operator << as a member function which seems exactly what I need here. The only way I can use the operator << is as friend which isn't helpful in this case. Can someone give me an idea how can I implement it as above?
Thank in advance,
Guy
Try the following:
class Report {
public:
Report() {}
Report(std::string _str) : stream(_str) {}
Report& operator <<(std::string str) {
if (stream.is_open())
stream << str;
return *this;
}
~Report() { stream.close(); }
std::ofstream stream;
};
For the above you must also include the <string> header.
It seems you want to create a stream-like type. Do not create a stream like type by overloading the output operator <<! The way to create a new stream-like type is to create a stream buffer (i.e., a type derived from std::streambuf) and use this to initialize an std::ostream object, probably by using std::ostream as a base class.
The other approaches for overloading operator<<() won't work for manipulators like std::endl: the manipulator std::endl is a function template and for deducing it template arguments when being used it is necessary to have an overload which can be used to deduce the type correct. The std::ostream class does this by providing suitable special overloads.
I realize that this isn't answering your question about how to overload operator<<() as a member but I think it is the wrong approach and it will probably yield better results changing the way the problem is addressed. I would provide more detail on how to create the corresponding classes but there isn't sufficient context given.
It seems like your problems stem from needing to insert different types to your report, such as "Heya!!!" or std::endl.
One flexible solution is to do this with templates.
You may implement it as a member function, where the Report is pointed to by this:
class Report {
public:
template < typename T >
Report& operator <<( const T &data ) { ... }
};
Or as a friend function, where there is no this and Report is instead explicitly mentioned and named:
class Report {
public:
template < typename T >
friend Report& operator <<( Report &r, const T &data ) { ... }
};
Or as a stand-alone function, if the Report has enough public methods to do the job.
template < typename T >
Report& operator <<( Report &r, const T &data ) { ... }
To implement it as a member function and be able to concatenate several streams you just have to return a reference to the object at the end of the function, e.g.:
class Report {
public:
// ...
Report& operator<<(const char *text) {
// write text to file...
return *this;
}
};
Here is a very simple example that prints to standard output instead of a file: http://codepad.org/S8QeJZ1x
If all you want is to make sure the file is closed after use, class Report is unnecessary. std::ofstream's destructor already closes its file.
The other answers so far, which try to define a templated operator<< have a problem: They won't work with some manipulators including std::endl, since it's actually a function template, and the compiler can't figure out what sort of instantiation it should use.
If the purpose of class Report is to add or modify something in the data going through, that's more easily and more correctly done by defining your own streambuf. This article by James Kanze describes how to do that.
Related
I made my own stream class inherited from std::ostream with a template insertion operator:
class MyOstream : public std::ostream
{
...
template <typename T>
std::ostream & operator << (T value)
{
...
return std::ostream::operator<<(value);
}
}
Also, I have a function that gets a reference to a std::ostream as an argument:
void some_func(std::ostream & stream)
{
stream << "Hello World!";
}
I want to somehow call MyOstream::operator<<() in some_func(), but the problem is that std::ostream::operator<<() is not virtual (actually, there are multiple overloaded operators + several friend operators) and I can't override it as usual.
Is there any way to do this without changing the interface of some_func()?
Addition
Function some_func(...) gets an object of MyOstream class as a parameter.
Addition #2
Actually I have my own MyStreambuf inherited from std::streambuf, which provides all the logic, MyOstream class is just needed to access to binary data. MyStreambuf class is used to restrict size of data, that user can write (let it be 500B). So, if object of MyStreambuf currently contains 450B of data and user will try to write 100B it'll cause setting of std::ios_base::badbit and refusing data. If user then try to write 10B, which is absolutely valid, it fails, cause of badbit set. That is the real problem.
So, the real problem I'm trying to overcome is calling clear() before each attempt to write.
In Java, the standard is to define the method toString() to return a string representation of a class. Other than overloading operator<<, is there any such standard in C++? I know there are the std::to_string() methods to get a string representation of a number. Does the C++ standard speak of defining the method to_string() to serve similar purpose for a class, or is there a common practice followed by C++ programmers?
The standard way to do this kind of thing is to provide an insertion operator so that an object can be inserted into a stream -- which may be any kind of stream, such as a stringstream.
If you wish, you can also provide a method that converts to a string (useful for your insertion operator), and, if you find the conversion acceptable, you can provide a 'to string' operator.
Here's my standard 'point' class example:
template <typename T>
struct point
{
T x;
T y;
point(): x(), y() { }
point( T x, T y ): x(x), y(y) { }
};
template <typename T>
std::ostream& operator << ( std::ostream& outs, const point <T> & p )
{
return outs << "(" << p.x << "," << p.y << ")";
}
I also tend to keep a handy function around to convert things to strings:
template <typename T>
std::string to_string( const T& value )
{
std::ostringstream ss;
ss << value;
return ss.str();
}
Now I can use it easily:
int main()
{
point p (2,-7);
std::cout << "I have a point at " << p << ".\n";
my_fn_which_takes_a_string( to_string(p) );
You'll find that the Boost Lexical Cast Library is also designed for this kind of thing.
Hope this helps.
The C++ standard does not prescribe a way to do this but it looks like there is a proposal which may introduce such an option Generic to_string/to_wstring functions which says in the motivation section which also highlights the current common practices being taken(which I demonstrate below):
For a long time C++ programmers have been looking for an easy way to
convert an object into its string representation. A typical answer to
this problem was to create a local ostringstream, insert the object
into the stream, and then obtain the resulting string with the str
member function. This solution is simple, safe, flexible and
extensible, though definitely too verbose for something that rather
ought to be a single function call. C++11 provided (a partial)
solution in the form of a set of overloaded to_string/to_wstring
functions. Unfortunately, these are limited only to the built-in
numeric types. Non-standard solutions exist too – most notably
boost::lexical_cast, which offers two-way conversion of objects and
strings, but lacks any formatting control.
This paper proposes a solution that:
generalizes the existing to_string/to_wstring functions for any type that provides a stream output operator and for any basic_string
specialisation,
remains consistent and mostly compatible with these functions,
provides extra formatting and concatenation capabilities,
is conceptually simple by building upon the familiar ostringstream solution.
There are two trip reports STL's and Herb Sutter's and I don't see this paper mentioned in either. So hopefully this will be covered in the post-Kona mailing when it comes out.
The first method they mentioned in the proposal would look something like the example in this answer:
class A {
public:
int i;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.i << ")";
}
combined with the something similar to the example from here:
template <typename T>
std::string to_string(const T& value) {
std::ostringstream os;
os << value;
return os.str();
}
We can find a boost::lexical_cast example in the question Enabling Classes for Use with boost::lexical_cast.
Looks like there is no standard way. As I understand C++ standard does not permit overloading of std::to_string function.
I ended up using one of these two solutions:
Solution #1
Instead of toString() method you can use:
operator std::string() const {
return "Object string.";
}
And to support streams you can add something like this:
friend std::ostream & operator <<(std::ostream &out, const YourClass &obj) {
return out << static_cast<std::string>(obj);
}
I hope that the << operator will just inline the conversion from the first operator.
Solution #2
Or you can go other way if you think often in the stream-style:
friend std::ostream & operator <<(std::ostream &out, const YourClass &obj) {
out << "Object ";
out << "string.";
return out;
}
And use it inside conversion operator:
operator std::string() const {
std::ostringstream out;
out << *this;
return out.str();
}
Either way this get you covered for most of the cases.
Does the C++ standard speak of defining the method to_string() to serve similar purpose for a class,
No.
or is there a common practice followed by C++ programmers.
No. However, I suspect every project has similar functionality. The name and return type most likely depend on the coding guidelines of a project.
At my work, we use
virtual QString toString() const = 0;
in one of our base classes.
You can start using something similar for your project.
virtual std::string toString() const = 0;
in your base class(es).
I have a value-semantic class that I'd like to be "showable" in the same sense as Haskells Show class, or Python provides a universal __str__() function.
In c++:
I could overload operator<<(ostream&, ...) so I can output my class to e.g. cout
I could overload operator std::string() so my class converts to std::string
I could overload operator const char*() so my class converts to const char *.
I could write a str() member, or a to_string(...) free function
Each of these functions could be defined in terms of the other. Is one option better over the others? Are these all the options? What would the most elegant way be to do this given c++11/14/17?
The question is going to be put in hold in a very few minutes, but I will still share my thoughts here.
First, of all, we can remove const char* / std::string() operator overloads from the list. If the class is not a string, it should not be convertible to string, and serialization enablement does not make your class a string.
As for str(), to_string and operator << they a pretty equivalent. However, since for any complex class to_string() and str() are very likely to use ostreams internally, I believe, operator << is the best option.
I don't know whether it's best practice or not but...
for debugging I always define operator<< which gives a summarised output in text form (this means it's easy to stream objects to log files)
for formatted output I would probably choose to implement this in terms of free functions: detail::x_detail_writer write_details(const X&) and then give detail::x_detail_writer (which is a functor) an operator<< overload
for anything but the most trivial object I implement to_string in terms of operator<< if at all.
for aiding with debugging output we have a helper class which goes something like this:
template<class T>
struct make_writeable {
friend std::ostream& operator<<(std::ostream& os, const T& t) {
// example prefix...
os << demangle(typeid(T).name()) << "{";
t.write(os);
// example postfix:
os << " }";
return os;
}
};
then derive some class from this and give it a member function called write:
struct X : make_writeable<X>
{
void write(std::ostream& os) const {
// write out members here. they will appear within the prefix and postfix
}
};
Im currently anwsering exercise questions concerning operator overloading in C++. I have a question:
Create a simple class containing an int and overload the operator+ as a member function. Also provide a print( ) member function that takes an ostream& as an argument and prints to that ostream&. Test your class to show that it works correctly.
I can create the class and write the operator+ function alright but I really dont understand the second part of the question. So far in my study of c++ I havent really come across ostream's and as such am not sure if its possible to explicitly create such a stream. I have tried using:
std::ostream o;
However this produces an error. Could someone please enlighten me on how I should create this function please?
So far in my study of c++ I havent really come across ostream's and as
such am not sure if its possible to explicitly create such a stream. I
have tried using: std::ostream o;
You must have missed something, because ostreams are important. std::cout is a variable of type std::ostream by the way. Usage is more or less like this
#include <iostream> //defines "std::ostream", and creates "std::ofstream std::cout"
#include <fstream> //defines "std::ofstream" (a type of std::ostream)
std::ostream& doStuffWithStream(std::ostream &out) { //defines a function
out << "apples!";
return out;
}
int main() {
std::cout << "starting!\n";
doStuffWithStream(std::cout); //uses the function
std::ofstream fileout("C:/myfile.txt"); //creates a "std::ofstream"
doStuffWithStream(fileout); //uses the function
return 0;
}
You don't create an ostream, you create an ostream reference, like your exercise question said. And you do it in the parameter list of your print function, i.e.
void print(std::ostream & os);
Then you can call that function, passing cout or any other object of a class derived from ostream(ofstream, ostringstream, etc...)
The question could be subjective, so the syntax of
std::ostream& operator << (std::ostream & o, const SomeClass &a) {
return o << a.accessor().. ;
}
When do you normally define this for the classes that you write, when do you avoid writing this friend function for your class.
IF I want to stream a class I normally write this:
std::ostream& operator << (std::ostream& o, const SomeClass& a)
{
a.print(o);
return o;
}
Then make print a const method on SomeClass that knows how to serialize the class to a stream.
I would only overload operator<< when that has anything to do with streaming, or with shifting and the class is purely numeral. For writing something into an ostream, as in your code, i think it's fine. Anything else, i think, will cause confusion and i would better use member functions for those other purposes. One other application, which i think i would still do as an exception to the rule, is doing something like this:
StringList list;
list << "foo" << "bar" << "baz";
It is how Qt does it with its string list, and which i find quite nice.
A benefit of Martin's answer above is that you also get polymorphism for free. If you make print(ostream&) a virtual function, then the << operator acts like a virtual function as well!
As to when to overload the operator, do so anytime you think the class should be able to be written to a stream (file, socket, etc...). This might even be only for debug purposes. It is often useful to be able to output the internals of a class, so there is no real downside to overloading this operator.
I would consider using it for something like logging. So you can do:
SystemLog systemLog;
systemLog << "Processing Item #15";
systemLog << "Error 0014: Bad things happened.";
systemLog << system.executeCommand(cmd); // returns a result string
Or maybe for networking as in:
NetworkInterface networkInterface;
string message("Hello World! I'm a server.");
networkInterface << message;
Of course implementing these things as regular function is also possible and might just be preferable. Generally, you should beware of operator overloading. Only use it when it really fits.
I had never ever overloaded this one in production code. Although you might want do this if you log a lot, it'll be useful.
I implement this if, and only if, I intend to make use of that operator. This is pretty much never... my reasons for not implementing it are therefore not using it. If its for public use then include it for completeness, but certainly I wouldn't include this in every class in a project of your own, since for the most part you will not need to output a class to a stream. e.g. If you wrap your entry point in a class, providing this operator will be pointless.
I do it very frequently since it makes dumping the object to a log for debugging really convenient.