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.
Related
I would like to initialise my class const member in the constructor from std::istream:
class MyClass {
private: const int dataMember;
public: MyClass(std::istream& is) { /* read into datamember }
}
I want to use >> operator of istream instance to fill in my dataMember but my dataMember is const. Is there any way in C++ to do that?
Sure, just wrap it in a function:
MyClass(std::istream& is) : dataMember{readInt(is)}{}
You can handle input errors by throwing from your helper function.
If you really want to do it without a helper function, you can force it with an istream_iterator:
MyClass(std::istream& is) : dataMember{*std::istream_iterator<int>(is)}{}
However, this will lead to somewhat wacky error handling. The error handling can be done via std::istream::exceptions, but the caller would have to remember to enable them. Otherwise, a failing read operation will invoke UB.
I prefer the helper function for that error handling reason. (Especially as it took me three iterations to get it right and I advocated UB in one.)
You can create a function that takes in a stream and returns an object. This function extracts the data from the stream and puts it in the constructor.
static MyClass fromIStream(std::istream& is) {
int datamember;
is >> datamember;
return MyClass(datamember);
}
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
}
};
I'm a bit confused about what exactly this line of code means in my header file.
friend ostream & operator << (ostream &, const something &);
Can someone clarify for me?
That line of code says that the operator << is a friend of something (since it's listed in the something class definition). This means that that operator << function can access the variables inside there.
The & here as the parameters mean that you pass in objects when calling the method and those parameters will just be another name for those parameter objects. Returning ostream & means that you're going to return the ostream parameter so that you can connect << expressions together avoiding creating a new "cout" when using the one global cout is what is needed.
As mentioned in many places, friend is a bypass to the normal protection mechanisms of C++ - it allows the function in question to access protected/private members, which normally only class members can do.
You'll often seen operators declared friends, because operators are never inside the class itself, but often need to modify something in the class and/or access private information. I.E. you may not want an external function to be able to muck with your internal pointers etc, but you may want to be able to print them out for status etc. You don't see them used very often otherwise - technically, it breaks encapsulation - but operators are kind of a special case.
A C++ class may declare another class or a function to be a friend. Friendly classes and methods may access private members of the class. So, the free operator method <<, not defined in any class, may insert somethings into a stream and look at and use the private members of something to do its work. Suppose something were complex:
class complex {
private:
double re;
double im;
public:
complex(double real = 0.0, double imag = 0.0) : re(real), im(imag) {}
friend ostream & operator<<(ostream& os, complex& c);
};
ostream & operator<<(ostream& os, complex& c){
os << c.re << std::showpos << c.im;
return os;
}
The friend keyword can name either functions or entire classes. In either case, it means that the implementation of the named function, or the named class, is allowed to access private and protected members of the class in which the friend declaration appears.
In this case, it means that this particular overload of the operator<< function is allowed to access internals of the something class, in order to write then to an output stream such as std::cout.
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.
I have a class (for logging) which derives from std::ostream. Stripped down, it looks like this:
class bsgs : public std::ostream {
public:
bsgs(const std::string& msg = "") {
// some setup work
}
~bsgs() {
// some cleanup work
}
template<typename T>
bsgs& operator<<(const T& rhs) {
os << rhs;
return *this;
}
private:
std::ostringstream os;
};
I wrote this class to do a few particular things I need like delta compression. Unfortunately, it doesn't work. I need to pass it to a third-party library (with source, but fairly
large and messy) that provides a "set_out" function to direct its output to a std::ostream. The
set_out function prototype is exactly this:
void set_out(std::ostream *out=0, int level=1);
and if I call it as:
set_out(&std::cout, 3);
or
set_out(&std::cerr, 5);
I get exactly the expected behavior. However, if I write:
bsgs logger;
set_out(&logger, 3);
I can see that the logger's constructor and destructor are called as expected but operator<< is never called. I'm not sure why, and I hope this is a simple question. If I can resolve this problem, I'm all set.
Does anyone know what exactly is going on? The problem seems to be that the library has no clue that I'm passing a pointer to a bsgs and not a std::ostream, but fixing the library to accept a wider range of objects than just std::ostream * looks like it might involve touching 500+ lines of code, which I'd like to avoid.
~~~~~~~~~~~~~~
Edit #1: I'm not sure if it is important, but the library has a virtual set_out() = 0; function at the top of its class hierarchy, which is implemented (identically, as far as I can see) in different subclasses. If I were writing the library I would have made set_out a (non-virtual) template function and provided with a specialization for std::ostream, but let users provide whatever they like so long as they define a usable operator<<. Making this change to the library looks like it will be a solid half a day of editing. Maybe there's an easier way?
The library has no clue that you're passing a pointer to a bsgs - you're not overriding a virtual function, there's no polymorphism involved.
You may find that implementing a streambuf and replacing a streams associated stream buffer (ostream::rdbuf) is a more viable solution.
You can always use
std::ostringstream os;
set_out(&os, 3);
When you want to derive from ostream, just create your own implementation of streambuf, which is virtual, and create stream like
std::ostream stream(new myStreamBuf);
set_out(&stream, 3);