I want to modify cout so that the text is displayed with, say, a 30ms delay between the printing of each character... I can't imagine I am the first person to want to do this using cout, but I also can't find any example of the same.
To be clear, I want to override the stream insertion operator (not overload).
I have already written my own output functions, I want to see if it is possible to modify the standard behavior for an entire solution.
You may do something like:
class MyDelayStream
{
public:
MyDelayStream(std::ostream& os) : os(os) {}
template <typename T>
MyDelayStream& operator <<(const T& t)
{
using namespace std::literals;
std::stringstream ss;
ss << t;
for (auto c : ss.str()) {
std::this_thread::sleep_for(30ms);
os << c;
}
return *this;
}
private:
std::ostream& os;
};
And then use it like:
MyDelayStream s(std::cout);
s << "hello" << 42 << '\n';
The hard (missing) part is manipulator and function as std::endl.
Related
I was trying to write a method that would take parameters using the >> operator as parameters similar to std::cin but I don't know how. Is it possible to create this kind of method that would take this stream like parameter, convert it properly (for example convert all ints to strings etc) and then save to an std::string variable?
Here is an example of how I would like to run the function:
int i = 0;
myMethod << "some text" << i << "moar text";
Inside that method I would like to take those parameters and store in a string.
Edit
I will try to explain exactly what this application is about: I Am trying to make a Clogger singleton class which will be used to save logs to a file. With this construction, I can call *CLogger::instance() << "log stuff"; from anywhere in the code and that's OK. Thanks to answers from this topic I have come to this. The problem is that each operator<< I use, then the object is going to be called. So if I do *CLogger::instance() << "log stuff " << " more stuff " << " even more";` this method(?) is going to be called 3 times:
template<typename T>
CLogger& operator<<(const T& t)
{
...
return *this;
}
That's not good for me as I intend to add some text before and after each log line. For example I would always like to add time before and std::endl after. Following the example I gave instead of getting:
[00:00] log stuff more stuff even more
I would get:
[00:00] log stuff
[00:00] more stuff
[00:00] even more
So I made an attempt to remove this behaviour by changing the method like this:
template<typename T>
CLogger& operator<<(const T& t)
{
ostringstream stream;
stream << t;
m_catString += stream.str();
if (stream.str() == "\n")
{
push_back(m_catString);
m_catString.clear();
}
return *this;
}
This way the program knows when to push new log line if I add "\n" at the end. Its nearly ok, as I bet I will forget to add this. Is there any more clever way?
You can't pass parameters to a method using <<, you need an object.
Something like this:
struct A
{
template<typename T>
A& operator<<(const T& t)
{
std::ostringstream stream;
stream << t;
data += stream.str();
return *this;
}
std::string data;
};
// ...
A a;
a << "Hello " << 34 << " World";
std::cout << a.data;
Regarding your update:
The most obvious thing is to implement the operator in CLogger instead and get rid of the Pusher class; that would let you write *CLogger::instance() << "sample text" << 10;
If you can't do that for some reason (you're giving out information piecemeal, so it's hard to tell), you can declare Pusher a friend and use the same method as everywhere else:
struct Pusher
{
template<typename T>
Pusher& operator<<(const T& t)
{
std::ostringstream stream;
stream << t;
CLogger::instance()->push_back(stream.str());
return *this;
}
};
The only way I know is creating a class class Method and then overload the operator<<, operators overloading
template<class T>
Method &operator<<(const T &x)
{
// Do whatever you like
return *this;
}
Then you can use it like :
Method myMethod;
myMethod << ... ;
you can look at this question about creating a cout-like class
std::cin and std::cout are not functions by the way
EDIT
class CLogger
{
...
template<typename T>
CLogger& operator<<(const T& t)
{
push_back(std::to_string(t));
return *this;
}
};
You don't have to create a class Pusher, just overload the operator in your first class, now you can use it with your object :
myCLogger << t; // this would call the function push back
I just wanted to know if there was some way yo be able to do this :
ofstream exemple (name);
exemple << Display();
Display() being a void method, that only do something like that :
cout << "Something" << endl;
I would do that because I have already written all the methods Display() for each class and I would like to put what they send to cout into my file, instead or recreate some methods "string Display()".
Is it possible?
Thank's! Marco
You can change cout's buffer, but cout is a global variable so that will affect the whole program.
Why don't you make Display() receive the output stream as parameter?
void Display(std::ostream &cout) {
cout << "Something" << endl;
}
No, not like that. You cannot use the result of a void function, ever, because it does not have one.
It is possible to hack around with the underlying buffer of std::cout, swapping it for example's, but I would not recommend this... and the code in your question would still be invalid.
You could do this:
#include <ostream>
#include <fstream>
void Display(std::ostream& os)
{
os << "Something" << std::endl;
}
int main()
{
const std::string name = "someFile.txt";
std::ofstream example(name);
Display(example);
}
You can make Display a helper function of a manipulator display_msg, a class which encapsulates the output. Display cannot return void, because if you are looking for the syntax os << Display() to work, Display will have to return something other than void.
Here is the definition of display_msg:
class display_msg { };
The class is left empty because it performs nothing of importance. We will overload the insertion operator for this class so that we can access the output stream and insert our custom data into:
std::ostream& operator<<(std::ostream& os, const display_msg&)
{
return os << "My message";
}
This is a very simple setup. But as you said, you would like for the output to be redirected to standard output ( std::cout ). For that you will have to copy the buffer of std::cout to the file stream. You can do that using RAII (in order to manage lifetime dependencies between the objects):
struct copy_buf
{
public:
copy_buf(std::ios& lhs, std::ios& rhs)
: str(lhs), buf(lhs.rdbuf())
{
lhs.rdbuf(rhs.rdbuf());
}
~copy_buf() { str.rdbuf(buf); }
private:
std::ios& str;
std::streambuf* buf;
};
The inserter can use this like so:
std::ostream& operator<<(std::ostream& os, const display_msg&)
{
copy_buf copy(os, std::cout);
return os << "My message";
}
Display is a simple helper function that returns the class:
display_msg Display()
{
return display_msg();
}
std::ifstream f("in.txt");
f << Display(); // redirects to standard output
I have a C++ class where I place many std::cout statements to print informative text messages about a mass of signals that this class is handling. My intentition is to redirect these text messages to a function named log. In this function, I have flag named mVerbose which defines if the log text should be printed. The content of this function is as follows:
void XXXProxy::log(std::stringstream& ss)
{
if(mVerbose)
{
std::cout << ss;
ss << "";
}
}
Then, the caller code snippet to this function is as follows:
std::stringstream logStr;
logStr << "SE"
<< getAddr().toString()
<< ": WAITING on epoll..."
<< std::endl;
log(logStr);
I would like to overload the << operator in my XXXProxy in a way that I can get rid of creating a std::stringstream object and calling the log function. I want to be able to log the text messages as below and let the << operator aggregate everything into:
<< "SE"
<< getAddr().toString()
<< ": WAITING on epoll..."
<< std::endl;
So I wouldlike to have an member << function that looks like:
void XXXProxy::operator << (std::stringstream& ss)
{
if(mVerbose)
{
std::cout << ss;
ss << "";
}
}
QUESTION
I am relatively a novice C++ developer and get lots of compilation errors when attemting to write the above stated like << operator. Could you please make some suggestions or direct me to some links for me to correctly implement this << operator. Thanks.
If you don't want to use std::cout directly and you want to have your own Log class, you could implement a simple wrapper providing the same interface of std::ostream: operator<<:
class Log {
private:
std::ostream& _out_stream;
//Constructor: User provides custom output stream, or uses default (std::cout).
public: Log(std::ostream& stream = std::cout): _out_stream(stream) {}
//Implicit conversion to std::ostream
operator std::ostream() {
return _out_stream;
}
//Templated operator>> that uses the std::ostream: Everything that has defined
//an operator<< for the std::ostream (Everithing "printable" with std::cout
//and its colleages) can use this function.
template<typename T>
Log& operator<< (const T& data)
{
_out_stream << data;
}
}
So if you implement std::ostream& operator>>(std::ostream& os , const YourClass& object) for your classes, you can use this Log class.
The advantage of this approach is that you use the same mechanism to make std::cout << your_class_object work, and to make the class work with the Log.
Example:
struct Foo
{
int x = 0; //You marked your question as C++11, so in class initializers
//are allowed.
//std::ostream::operator<< overload for Foo:
friend std::ostream& operator<<(std::ostream& os , const Foo& foo)
{
os << foo.x;
}
};
int main()
{
Log my_log;
Foo my_foo;
my_foo.x = 31415;
my_log << my_foo << std::endl; //This prints "31415" using std::cout.
}
Possible improvements:
You could write a extern const of class Log, and make the class implement a singleton. This allows you to access the Log everywhere in your program.
It's common in log outputs to have a header, like Log output (17:57): log message. To do that, you could use std::endl as a sentinel and store a flag that says when the next output is the beginning of a line (the beginning of a log message). Checkout the next answer for a complete and working implementation.
References:
std::ostream
operator<< for std::ostream
std::enable_if
std::is_same
decltype specifier
The timestamp of the example was only that, an example :).
But if you like that, we could try to implement it. Thankfully to C++11 and its STL's big improvements, we have an excellent time/date API: std::chrono
std::chronois based in three aspects:
Clocks
Durations
Time points
Also, chrono provides three types of clocks, std::system_clock, std::steady_clock , and std::high_resolution_clock. In our case, we use std::system_clock (We want access to the date-time, not meassuring precise time intervals).
For more info about std::chrono, checkout this awsome Bo Qian's youtube tutorial.
So if we have to implement a time stamp for our log header, we could do this:
EDIT: Like other good things, C++ templates are good tools until you overuse it.
Our problem was that std::endl is a templated function, so we cannot pass it directly to
annother templated function as parammeter (operator<< in our case), because the compiler cannot deduce std::endl template argumments directly. Thats the recurrent error "unresolved overloaded function type".
But there is a much simpler way to do this: Using an explicit overload of operator<< for std::endl only, and other templated for everything else:
class Log
{
private:
std::ostream& _out_stream;
bool _next_is_begin;
const std::string _log_header;
using endl_type = decltype( std::endl ); //This is the key: std::endl is a template function, and this is the signature of that function (For std::ostream).
public:
static const std::string default_log_header;
//Constructor: User passes a custom log header and output stream, or uses defaults.
Log(const std::string& log_header = default_log_header , std::ostream& out_stream = std::cout) : _log_header( log_header ) , _out_stream( out_stream ) , _next_is_begin( true ) {}
//Overload for std::endl only:
Log& operator<<(endl_type endl)
{
_next_is_begin = true;
_out_stream << endl;
return *this;
}
//Overload for anything else:
template<typename T>
Log& operator<< (const T& data)
{
auto now = std::chrono::system_clock::now();
auto now_time_t = std::chrono::system_clock::to_time_t( now ); //Uhhg, C APIs...
auto now_tm = std::localtime( &now_time_t ); //More uhhg, C style...
if( _next_is_begin )
_out_stream << _log_header << "(" << now_tm->tm_hour << ":" << now_tm->tm_min << ":" << now_tm->tm_sec << "): " << data;
else
_out_stream << data;
_next_is_begin = false;
return *this;
}
};
const std::string Log::default_log_header = "Log entry";
This code snippet works perfectly. I have pushed the complete implementation to my github account.
Reference:
std::chrono
std::chrono::system_clock
std::chrono::system_clock::now()
std::time_t
std::chrono::system_clock::to_time_t()
std::tm
std::localtime()
Is it possible to write a method that takes a stringstream and have it look something like this,
void method(string str)
void printStringStream( StringStream& ss)
{
method(ss.str());
}
And can be called like this
stringstream var;
printStringStream( var << "Text" << intVar << "More text"<<floatvar);
I looked up the << operator and it looks like it returns a ostream& object but I'm probably reading this wrong or just not implementing it right.
Really all I want is a clean way to concatenate stuff together as a string and pass it to a function. The cleanest thing I could find was a stringstream object but that still leaves much to be desired.
Notes:
I can't use much of c++11 answers because I'm running on Visual Studio 2010 (against my will, but still)
I have access to Boost so go nuts with that.
I wouldn't be against a custom method as long as it cleans up this mess.
Edit:
With #Mooing Duck's answer mixed with #PiotrNycz syntax I achieved my goal of written code like this,
try{
//code
}catch(exception e)
{
printStringStream( stringstream() << "An exception has occurred.\n"
<<" Error: " << e.message
<<"\n If this persists please contact "<< contactInfo
<<"\n Sorry for the inconvenience");
}
This is as clean and readable as I could have hoped for.
Hopefully this helps others clean up writing messages.
Ah, took me a minute. Since operator<< is a free function overloaded for all ostream types, it doesn't return a std::stringstream, it returns a std::ostream like you say.
void printStringStream(std::ostream& ss)
Now clearly, general ostreams don't have a .str() member, but they do have a magic way to copy one entire stream to another:
std::cout << ss.rdbuf();
Here's a link to the full code showing that it compiles and runs fine http://ideone.com/DgL5V
EDIT
If you really need a string in the function, I can think of a few solutions:
First, do the streaming seperately:
stringstream var;
var << "Text" << intVar << "More text"<<floatvar;
printStringStream(var);
Second: copy the stream to a string (possible performance issue)
void printStringStream( ostream& t)
{
std::stringstream ss;
ss << t.rdbuf();
method(ss.str());
}
Third: make the other function take a stream too
Make your wrapper over std::stringstream. In this new class you can define whatever operator << you need:
class SSB {
public:
operator std::stringstream& () { return ss; }
template <class T>
SSB& operator << (const T& v) { ss << v; return *this; }
template <class T>
SSB& operator << (const T* v) { ss << v; return *this; }
SSB& operator << (std::ostream& (*v)(std::ostream&)) { ss << v; return *this; }
// Be aware - I am not sure I cover all <<'s
private:
std::stringstream ss;
};
void print(std::stringstream& ss)
{
std::cout << ss.str() << std::endl;
}
int main() {
SSB ssb;
print (ssb << "Hello" << " world in " << 2012 << std::endl);
print (SSB() << "Hello" << " world in " << 2012 << std::endl);
}
For ease of writing objects that can be inserted into a stream, all these classes overload operator<< on ostream&. (Operator overloading can be used by subclasses, if no closer match exists.) These operator<< overloads all return ostream&.
What you can do is make the function take an ostream& and dynamic_cast<> it to stringstream&. If the wrong type is passed in, bad_cast is thrown.
void printStringStream(ostream& os) {
stringstream &ss = dynamic_cast<stringstream&>(os);
cout << ss.str();
}
Note: static_cast<> can be used, it will be faster, but not so bug proof in the case you passed something that is not a stringstream.
Since you know you've got a stringstream, just cast the return value:
stringstream var;
printStringStream(static_cast<stringstream&>(var << whatever));
Just to add to the mix: Personally, I would create a stream which calls whatever function I need to call upon destruction:
#include <sstream>
#include <iostream>
void someFunction(std::string const& value)
{
std::cout << "someFunction(" << value << ")\n";
}
void method(std::string const& value)
{
std::cout << "method(" << value << ")\n";
}
class FunctionStream
: private virtual std::stringbuf
, public std::ostream
{
public:
FunctionStream()
: std::ostream(this)
, d_function(&method)
{
}
FunctionStream(void (*function)(std::string const&))
: std::ostream(this)
, d_function(function)
{
}
~FunctionStream()
{
this->d_function(this->str());
}
private:
void (*d_function)(std::string const&);
};
int main(int ac, char* av[])
{
FunctionStream() << "Hello, world: " << ac;
FunctionStream(&someFunction) << "Goodbye, world: " << ac;
}
It is worth noting that the first object sent to the temporary has to be of a specific set of types, namely one of those, the class std::ostream knows about: Normally, the shift operator takes an std::ostream& as first argument but a temporary cannot be bound to this type. However, there are a number of member operators which, being a member, don't need to bind to a reference! If you want to use a user defined type first, you need to extract a reference temporary which can be done by using one of the member input operators.
I'd like to implement a custom manipulator for ostream to do some manipulation on the next item being inserted into the stream. For example, let's say I have a custom manipulator quote:
std::ostringstream os;
std::string name("Joe");
os << "SELECT * FROM customers WHERE name = " << quote << name;
The manipulator quote will quote name to produce:
SELECT * FROM customers WHERE name = 'Joe'
How do I go about accomplishing that?
Thanks.
It's particularly difficult to add a manipulator to a C++ stream, as one has no control of how the manipulator is used. One can imbue a new locale into a stream, which has a facet installed that controls how numbers are printed - but not how strings are output. And then the problem would still be how to store the quoting state safely into the stream.
Strings are output using an operator defined in the std namespace. If you want to change the way those are printed, yet keeping the look of manipulators, you can create a proxy class:
namespace quoting {
struct quoting_proxy {
explicit quoting_proxy(std::ostream & os):os(os){}
template<typename Rhs>
friend std::ostream & operator<<(quoting_proxy const& q,
Rhs const& rhs) {
return q.os << rhs;
}
friend std::ostream & operator<<(quoting_proxy const& q,
std::string const& rhs) {
return q.os << "'" << rhs << "'";
}
friend std::ostream & operator<<(quoting_proxy const& q,
char const* rhs) {
return q.os << "'" << rhs << "'";
}
private:
std::ostream & os;
};
struct quoting_creator { } quote;
quoting_proxy operator<<(std::ostream & os, quoting_creator) {
return quoting_proxy(os);
}
}
int main() {
std::cout << quoting::quote << "hello" << std::endl;
}
Which would be suitable to be used for ostream. If you want to generalize, you can make it a template too and also accept basic_stream instead of plain string. It has different behaviors to standard manipulators in some cases. Because it works by returning the proxy object, it will not work for cases like
std::cout << quoting::quote;
std::cout << "hello";
Try this:
#include <iostream>
#include <iomanip>
// The Object that we put on the stream.
// Pass in the character we want to 'quote' the next object with.
class Quote
{
public:
Quote(char x)
:m_q(x)
{}
private:
// Classes that actual does the work.
class Quoter
{
public:
Quoter(Quote const& quote,std::ostream& output)
:m_q(quote.m_q)
,m_s(output)
{}
// The << operator for all types. Outputs the next object
// to the stored stream then returns the stream.
template<typename T>
std::ostream& operator<<(T const& quoted)
{
return m_s << m_q << quoted << m_q;
}
private:
char m_q;
std::ostream& m_s;
};
friend Quote::Quoter operator<<(std::ostream& str,Quote const& quote);
private:
char m_q;
};
// When you pass an object of type Quote to an ostream it returns
// an object of Quote::Quoter that has overloaded the << operator for
// all types. This will quote the next object and the return the stream
// to continue processing as normal.
Quote::Quoter operator<<(std::ostream& str,Quote const& quote)
{
return Quote::Quoter(quote,str);
}
int main()
{
std::cout << Quote('"') << "plop" << std::endl;
}
[EDIT: "True manipulator semantics" (i.e. a persistent quoting state) could also be achieved by wrapping an std::ostream rather than deriving from it, as noted by BenĂ´it in the comments.]
To the best of my knowledge this cannot be done directly without either deriving a new class from std::ostream or similar, or wrapping such a class in another class that forwards most methods to its contained std::ostream object. That's because, for the code example you provide to work, you will need to somehow modify the behaviour of std::ostream& operator<<(std::ostream&, std::string const&), which is defined somewhere in the iostreams hierarchy (or possibly wherever std::string is defined). You will also need to use the (somewhat ugly) facilities in ios_base to record a boolean flag holding the current quoting state. Look up ios_base::xalloc(), ios_base::iword() and ios_base::pword() to find out how to do that.
However, if you are willing to use the following syntax:
os << "SELECT * FROM customers WHERE name = " << quote(name);
This can be done very simply using a global function (in an appropriate namespace of course).
This syntax has the advantage that quoting is not persistent, meaning it can't "leak out" when a function sets the quote formatting flag and forgets to set it back to its original value.
Or just use OTL which basically already implements a stream interface for SQL very similarly to your example.