I am trying to overload the stream operator as a diagnostic tool for various objects in my code. Ideally I would like to be able to modify the stream on the fly with those stream modifier flags, however these are very limited and I don't really want to sprinkle setVerbose flags in each of my objects. I ended up with the following rather poor but working solution
#include <iostream>
#include <string>
#include <vector>
struct StructA {
std::string mLongName;
std::string mShortName;
inline friend std::ostream& operator << (std::ostream& os, const StructA& rStruct) {
// I dont know how to use a generic verbose flag - so use this - very bad idea
// but perhaps the stackoverflow people can help out with a good suggestion
if (os.flags() & os.skipws) {
os << rStruct.mShortName << std::endl;
} else {
os << rStruct.mLongName << std::endl;
}
return os;
}
};
int main()
{
StructA test {"Verbose Name", "Short Name"};
std::cout << test << std::noskipws << test << test << std::skipws << test;
}
I created the above live example to demonstrate my point, and it prints the following output:
Short Name
Verbose Name
Verbose Name
Short Name
As you can see, I am using a totally inappropriate 'skipws' stream modifier flag as a poor man's 1 level verbose flag - that was just to show the in stream approach I was looking for without havnig to add a member object to each of my printable objects (all suggestions for better approaches would be welcome but I would like to minimize the changes to each of my printable objects - as I have quite a lot). Secondly the flag is persistent until reset later - some other stream flags only last for the next stream operator but I am not exactly sure how that works and thirdly
You can store custom state in your stream instance:
See it Live On Coliru
#include <iostream>
static int const index = std::ios_base::xalloc();
std::ostream& verbose(std::ostream& stream) {
stream.iword(index) = 1;
return stream;
}
std::ostream& noverbose(std::ostream& stream) {
stream.iword(index) = 0;
return stream;
}
struct StructA {
std::string mLongName;
std::string mShortName;
inline friend std::ostream& operator << (std::ostream& os, const StructA& rStruct) {
switch (os.iword(index)) {
case 1: return os << rStruct.mLongName;
case 0:
default: return os << rStruct.mShortName;
}
}
};
int main()
{
StructA a;
a.mLongName = "loooooooooooooooooooong names are tedious";
a.mShortName = "succinctness";
std::cout << a << '\n';
std::cout << verbose;
std::cout << a << '\n';
std::cout << noverbose;
std::cout << a << '\n';
}
Credits go to Dietmar Kühl's answer.
If you needed siginificant amounts of state/logic, you would have to look at imbue-ing a custom locale facet. His answer shows the basics of this approach too.
It seems you are in this case too reluctant to create an abstraction for some reason. Don't take this personally I only write this because I once was too hesitant to do that, but create abstractions. Create a Logger class based on iostream either by inheritance or containment which behavior you can modify. Let's say the logger has options like
enum {SHORT,VERBOSE,DEBUG};
Let this option be static so that it has application wide effect on all the instances. Really there only needs to be one instance perhaps?
I realize that all your printable objects need to support the various printing options in a consistent way, i.e. all need to have shortName and longName.
Related
It makes sense to implement << for QString like:
std::ostream& operator <<(std::ostream &stream,const QString &str)
{
stream << str.toAscii().constData(); //or: stream << str.toStdString(); //??
return stream;
}
instead of writing
stream << str.toAscii().constData();
every time in the code.
However, since it is not in standard Qt library, I'm assuming there is any particular reason not to do so. What are the risks/inconvenience of overloading << as specified above?
If the << operator is included in the Qt library every client of the library will have to use the exact same implementation. But due to the nature of QString it is far from obvious this is what these clients want. Some people writing software interacting with legacy file in western europe may want to use Latin1() characters, US people may go with Ascii() and more modern software may want to use Utf8().
Having a single implementation in the library would restrict unacceptably what can be done with the whole library.
It's not necessary to implement such thing, as long as there exists a convenient solution like this one, involving QTextStream
QString s;
QTextStream out(&s);
out << "Text 1";
out << "Text 2";
out << "And so on....";
QTextStream is quite powerfull...
The accepted answer points out some valid reasons for why there is no operator<< function for QString.
One can easily overcome those reasons by providing some convenience functions and maintaining some state in an application specific namespace.
#include <iostream>
#include <QString>
namespace MyApp
{
typedef char const* (*QStringInsertFunction)(QString const& s);
char const* use_toAscii(QString const& s)
{
return s.toAscii().constData();
}
char const* use_toUtf8(QString const& s)
{
return s.toUtf8().constData();
}
char const* use_toLatin1(QString const& s)
{
return s.toLatin1().constData();
}
// Default function to use to insert a QString.
QStringInsertFunction insertFunction = use_toAscii;
std::ostream& operator<<(std::ostream& out, QStringInsertFunction fun)
{
insertFunction = fun;
return out;
}
std::ostream& operator<<(std::ostream& out, QString const& s)
{
return out << insertFunction(s);
}
};
int main()
{
using namespace MyApp;
QString testQ("test-string");
std::cout << use_toAscii << testQ << std::endl;
std::cout << use_toUtf8 << testQ << std::endl;
std::cout << use_toLatin1 << testQ << std::endl;
return 0;
}
Output:
test-string
test-string
test-string
I don't think there is any particular reason for excluding (nor including) this in the Qt library. Only problem that could possibly appear here is a possibility that std::ostream object could modify the contents of the parameter passed to std::ostream::operator<< function.
However, in the reference it is clearly stated that this function will modify the parameter if string buffer is passed - there is nothing about the other types, so I guess (and the common-sense is telling me) that operator<< will not modify char* parameter. Also, on this page there is nothing about modifying the passed object.
Last thing: instead of using QString::toAscii().constData(), you could use QString::toStdString() or qPrintable(const QString&) macro.
I snipped the irrelevant parts out of my class here. I don't know what I'm doing wrong, just trying to be able to cout << the object.
#include <iostream>
class Snipped
{
public:
friend std::ostream& operator<<(std::ostream& os, const Snipped& s);
protected:
private:
};
std::ostream& operator<<(std::ostream& os, const Snipped& s)
{
os << "test";
return os;
}
int main(int argc, char* argv[])
{
Snipped* s = new Snipped();
std::cout << s << std::endl << s;
delete s;
return 0;
}
Expected output:
test
test
Actual output:
0x12ae20
0x12ae20 (random memory location?)
std::cout << s << std::endl << s;
You are calling << with an address, you need to call it with object of type Snipped.
The line of code above won't call your overloaded operator function because the parameters of the overloaded function do not match.
You need to call:
std::cout << *s << std::endl << *s;
This ensures your << overloaded operator function is called because the parameters match to it.
Try
std::cout << *s << std::endl;
By the way,
std::cout << s << std::endl;
is not really a random memory location.
It is the actual memory address on the heap, in this case.
You can actually use that address to check the identity of an object.
That's useful while debugging, or in actual code.
For example, if you look at assignment operators, you will often see:
class Foo
{
Foo& operator=( const Foo& foo )
{
// use the identity principle
if ( &foo==this )
return *this; // so I don't waste CPU cycles copying to myself
// ...really do copy here
return *this;
}
};
Although just dereferencing the pointer (i.e. to use '*s' instead of 's') there is a bigger fish to fry! Unless there is a good reason for putting an object on the heap you shouldn't do so:
int main()
{
Snipped s;
std::cout << s << '\n' << s;
}
I found the use of new and more so delete quite rare in the programs I write. Aside from simpler code this conveniently also often yields faster programs. If you really need to allocate something on the heap, use some sort of a smart pointer to make sure the object is automatically released:
int main()
{
std::unique_ptr<Snipped> s(new Snipped);
std::cout << *s << '\n' << *s;
}
As a side note, don't use std::endl either unless you really intend to flush the stream: I found inappropriate use of std::endl to be the root cause of massive performance problems more than once. Sure most of the time it doesn't matter but in even more cases you don't care about the flush. If you don't like using '\n' or "\n" you can instead use a custom manipulator:
std::ostream& nl(std::ostream& out) { return out << '\n'; }
With this you can use nl instead of std::endl and don't suffer from always flushing the stream.
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.
I want to output my own object to a STL stream but with customized formatting. I came up with something like this but since I never used locale and imbue before I have no idea if this makes sense and how to implement MyFacet and operator<<.
So my questions are: does this make sense and how to implement MyFacet and operator<< ?
The following is a simplified example which shows you what I want to do.
struct MyObject
{
int i;
std::string s;
};
std::ostream &operator<<(std::ostream &os, const MyObject &obj)
{
if (????)
{
os << obj.i;
}
else
{
os << obj.s;
}
}
MyObject o;
o.i = 1;
o.s = "hello";
std::cout.imbue(locale("", new MyFacet(MyFacet::UseInt)));
std::cout << o << std::endl; // prints "1"
std::cout.imbue(locale("", new MyFacet(MyFacet::UseString)));
std::cout << o << std::endl; // prints "hello"
Implementing your own operator << for tracing is generally a good idea. However I've never needed to imbue locales. However I tried it and it worked fine. Here's what I did:
class my_facet : public std::locale::facet
{
public:
enum option{
use_string,
use_numeric
};
//Unique id for facet family, no locale can contain two
//facets with same id.
static std::locale::id id;
my_facet(option o=use_numeric):
facet(0),
_option(o)
{//Initialize reference count to zero so that the memory
//management will be handled by locale
};
option get_option() const {return _option;};
protected:
option _option;
};
std::locale::id my_facet::id(123456); //Facet family unique id
std::ostream& operator<<(std::ostream& os, const myobj& o)
{
std::locale const& l = os.getloc();
if( std::has_facet<my_facet>(l) ){
my_facet const& f = std::use_facet<my_facet>(l);
switch(f.get_option()){
case my_facet::use_numeric:
os << "Using numeric! ";
break;
case my_facet::use_string:
os << "Using string! ";
break;
default:
os << "Unhandled case.. ";
break;
}
return os;
}
os << "Default case when no facet has been set";
return os;
}
Then to imbue a locale with the facet:
std::locale mylocale(locale("US"), new my_facet(my_facet::use_numeric));
std::cout.imbue(mylocale);
However a more elegant way would be to implement different facets of the same facet family that can be replaced in the locale.
Well, a locale is generally used to allow different output/input formatting of the same object based on the local (the specified locale in fact) formatting which is present. For a good article on this see: http://www.cantrip.org/locale.html. Now maybe its because your example above is quite simplified, but to me it looks like you are trying to come up with a clever way to switch between printing one part of an object or another. If that is the case it might be simpler do just overload the stream operator for each type and use the if switch externally.
Anyway, I'm not going to pretend that I'm an expert in facets and locales but have a look at that article, its pretty thorough and will give you a better explanation than I will!
I'm trying to implement my own qDebug() style debug-output stream, this is basically what I have so far:
struct debug
{
#if defined(DEBUG)
template<typename T>
std::ostream& operator<<(T const& a) const
{
std::cout << a;
return std::cout;
}
#else
template<typename T>
debug const& operator<<(T const&) const
{
return *this;
}
/* must handle manipulators (endl) separately:
* manipulators are functions that take a stream& as argument and return a
* stream&
*/
debug const& operator<<(std::ostream& (*manip)(std::ostream&)) const
{
// do nothing with the manipulator
return *this;
}
#endif
};
Typical usage:
debug() << "stuff" << "more stuff" << std::endl;
But I'd like not to have to add std::endl;
My question is basically, how can I tell when the return type of operator<< isn't going to be used by another operator<< (and so append endl)?
The only way I can think of to achieve anything like this would be to create a list of things to print with associated with each temporary object created by qDebug(), then to print everything, along with trailing newline (and I could do clever things like inserting spaces) in ~debug(), but obviously this is not ideal since I don't have a guarantee that the temporary object is going to be destroyed until the end of the scope (or do I?).
Something like this will do:
struct debug {
debug() {
}
~debug() {
std::cerr << m_SS.str() << std::endl;
}
public:
// accepts just about anything
template<class T>
debug &operator<<(const T &x) {
m_SS << x;
return *this;
}
private:
std::ostringstream m_SS;
};
Which should let you do things like this:
debug() << "hello world";
I've used a pattern like this combined with a lock to provide a stream like logging system which can guarantee that log entries are written atomically.
NOTE: untested code, but should work :-)
Qt uses a method similar to #Evan. See a version of qdebug.h for the implementation details, but they stream everything to an underlying text stream, and then flush the stream and an end-line on destruction of the temporary QDebug object returned by qDebug().
When you write that this is the typical usage:
debug() << "stuff" << "more stuff" << std::endl;
are you definitely planning to construct a debug object each time you use it? If so, you should be able to get the behavior you want by having the debug destructor add the newline:
~debug()
{
*this << std::endl;
... the rest of your destructor ...
}
That does mean you cannot do something like this:
// this won't output "line1" and "line2" on separate lines
debug d;
d << "line1";
d << "line2";
The stream insertion (<<) and extraction (>>) are supposed to be non-members.
My question is basically, how can I
tell when the return type of
operator<< isn't going to be used by
another operator<< (and so append
endl)?
You cannot. Create a member function to specially append this or append an endl once those chained calls are done with. Document your class well so that the clients know how to use it. That's your best bet.