I am trying to make a Console class. I would like to wrap cin and cout in the class and overload the << and >> operators. So I could use the class as such:
// Output
Console << "Call cout from Console" << endl;
// Input
string str;
Console >> str; // Call cin
My best guess was:
class Console {
//...
public:
ostream& operator<< (ostream& os)
{
cout << os;
return &cout;
}
//...
};
But I know that's wrong, how could I overload the operators to use the Console class as both cin and cout?
I got a working code that can handle the stream manipulators. You can see my code in action in this Ideone page
Here is the code:
#include <iostream>
typedef std::ostream& (*manip) (std::ostream&);
class console {
};
template <class T> console& operator<< (console& con, const T& x) { std::cout << x; return con; }
template <class T> console& operator>>(console& con, T& x) { std::cin >>x; return con; }
console& operator<< (console& con, manip manipulator){ std::cout<<manipulator; return con;}
int main() {
console c;
int a,b;
c>>a>>b;
c << "hello world"<<std::endl<<std::hex<<(a+b)<<std::endl;
}
Thanks #MooingDuck for the discussion that led me to a working answer and #111111 for the start point.
I don't know why would want to do such a thing but it isn't the stream you need to capture but the other type. But if this is just to make std::cout and std::cin more convenient I wouldn't bother.
class console {
};
template<typename T>
console& operator<<(console con, const T& val) {
std::cout << val;
return con;
}
console c;
c << "hello world\n";
This is not direct answer to your question, but maybe I point you out some alternative.
See my answer to some other question. To define yourself all of these <<and >> operators is not very easy. However you can overwrite streambuf for Console. Use combined streambufs of cin and cout,
Derive your console from std::iostream and your streambuf from std::streambuf
class console_streambuf : public std::streambuf {
public:
console_streambuf() {
// no buffering, overflow on every char
setp(0, 0);
}
virtual int_type overflow(int_type c) {
std::cout << c;
return c;
}
...
};
class console : public std::iostream {
public:
console() { rdbuf(&buf); }
private:
console_streambuf buf;
};
Contrary to many of the answers above, doing what you want is pretty simple, using the magic of templates.
I'd recommend using a stringstream, because using an ostream (cout is an ostream) can require arcane black magic (no joke).
#include <string>
#include <iostream>
#include <sstream>
struct console {
std::stringstream data_;
console() : data_() { };
// We make ourselves a template sink so we can "take" operator<<'s.
// The awesome advantage to using a template like this is that the
// compiler will allow us to "take" any data that can be converted
// to a stringstream, which will handle converting int's etc.
// for us!
template<typename T>
console& operator<<(const T& what) {
data_ << what;
return *this; // We must return a reference if we want to
// string together more than one thing, i.e.
// b << " " << 4;
}
void flush() {
std::cout << data_.str();
data_.clear();
std::cout.flush();
}
};
int main()
{
int a = 4;
console b;
console c;
b.data_ << 2;
c.data_ << 4;
//b << std::cout; // WHAT? it's possible but stupid, prints garbage
// Because we made the template return a reference, this will
// allow us to chain things just like we do with cout.
b << " HELLO WORLD! " << "yo!" << 4;
b << a << " " << 4.2f;
// Compiler chokes on this. It will try to convert "console"
// to a stringstream which it can't.
//b << c;
b.flush(); // Send out the output
// Wait for key press
char foo[500];
gets(foo);
}
Output:
2 HELLO WORLD! yo!44 4.2
Just like cout, except of course with more control.
You can get into using basic_ostream's and basic_istreams if you want binary I/O, but I'd recommend against it unless you really really need it.
Overloaded operator functions must be declared with the specific types you're going to call them with on the left and right. So you will need an operator<< (int), operator<< (double), operator<< (const std::string &), etc.
If you're really just going to pass them on to cin and cout, you can save typing by using a template member function, like:
template <class T> Console& operator<< (const T& x) { cout << x; return *this; }
[thanks to André for pointing out it should return Console& so you can string together calls like Console << a << b; ]
Related
I'm currently writing a class to wrap stringstream. My overall goal is to provide a threadsafe << (ostream) for my stringstream. I'm having trouble figuring out the correct syntax of what I'm trying to do. Any help would be most appreciative!
Below you'll find what I've tried. I know this is not the correct syntax, but it is kind of what I'm shooting for. I could of course not overload the << operator and force users to use the AddValue, but that wouldn't be ideal for quick and easy string manipulation while writing the code.
class WrappedStringStream
{
public :
WrappedStringStream() ;
template<typename T>
void AddValue( const T & value )
{
m_mutex.Lock() ;
//here I'd like to do something like m_stringstream << value, but of course since
//I'm overloading operator<< that won't work
m_mutex.Unlock() ;
}
friend std::ostream & operator<<( std::ostream & out, const WrappedStringStream & string )
{
string.AddValue( out ) ;
return out ;
}
protected :
std::stringstream m_stringstream ;
mutable Mutex m_mutex ;
}
As mentioned above it doesn't compile, which I understand since I'm passing WrappedStringStream as a const parameter and calling AddValue which isn't const - resulting in the discards qualifier error.
Here is the solution
#include <iostream>
#include <sstream>
#include <mutex>
using namespace std;
class MutexWrapper
{
private:
mutex& m_mutex;
public:
MutexWrapper(mutex& mtx) : m_mutex(mtx) { mtx.lock () ; };
~MutexWrapper() { m_mutex.unlock () ; };
};
class WrappedStringStream
{
public :
WrappedStringStream() { };
template<typename T>
std::ostream & operator<<(const T& value)
{
MutexWrapper wrapper(m_mutex);
return m_stringstream << value;
}
void showStream()
{
cout << m_stringstream.str();
}
protected :
stringstream m_stringstream;
mutable mutex m_mutex ;
};
int main()
{
WrappedStringStream ws;
ws << "This is a string, " << 5 << 6.78;
ws.showStream();
return 0;
}
Output
This is a string, 56.78
======== edit ==========
Originally I was not quiet understand what the questioner's final goal, but just focus on how to fix his syntax issue.It is not a good idea to use << in a multithreading environment. We have a Log class, and in our log class we only have a Log method which takes variable amount of parameters. That will solve the problem.
Still, there is a solution for using << to lock the thread, but really urgly and NOT recommend. Downside is obvious - if you forgot to add the 'LoggingStart' and 'LoggingEnd', you might caught deadlock.
Also thanks #RemyLebeau, It should return *this instead of m_stringstream.
Please see code below.
#include <iostream>
#include <sstream>
#include <mutex>
using namespace std;
class WrappedStringStream
{
public:
enum StreamSignals
{
LoggingStart,
LoggingEnd
};
WrappedStringStream() { };
std::ostream & operator<<(const StreamSignals& signal)
{
if (signal == LoggingStart)
m_mutex.lock();
else if (signal == LoggingEnd)
m_mutex.unlock();
return *this;
}
template<typename T>
std::ostream & operator<<(const T& value)
{
m_stringstream << value;
return *this;
}
void showStream()
{
cout << m_stringstream.str();
}
protected :
stringstream m_stringstream;
mutable mutex m_mutex ;
};
int main()
{
WrappedStringStream ws;
ws << WrappedStringStream::StreamSignals::LoggingStart;
ws << "This is a string, " << 5 << 6.78;
ws << WrappedStringStream::StreamSignals::LoggingEnd;
ws.showStream();
return 0;
}
Given some type that is streamable:
struct X {
int i;
friend std::ostream& operator<<(std::ostream& os, X const& x) {
return os << "X(" << x.i << ')';
}
};
I want to append this onto a std::string. I can implement this as:
void append(std::string& s, X const& x) {
std::ostringstream os;
os << x;
s.append(os.str());
}
But this seems lame since I'm writing data into one stream just to then allocate a new string just for the purposes of appending it onto a different one. Is there a more direct route?
This can be solved by a new type of streambuf (see Standard C++ IOStreams and Locales: Advanced Programmer's Guide and Reference).
Here is a sketch of how it can look:
#include <streambuf>
class existing_string_buf : public std::streambuf
{
public:
// Store a pointer to to_append.
explicit existing_string_buf(std::string &to_append);
virtual int_type overflow (int_type c) {
// Push here to the string to_append.
}
};
Once you flesh out the details here, you could use it as follows:
#include <iostream>
std::string s;
// Create a streambuf of the string s
existing_string_buf b(s);
// Create an ostream with the streambuf
std::ostream o(&b);
Now you just write to o, and the result should appear as appended to s.
// This will append to s
o << 22;
Edit
As #rustyx correctly notes, overriding xsputn is required for improving performance.
Full Example
The following prints 22:
#include <streambuf>
#include <string>
#include <ostream>
#include <iostream>
class existing_string_buf : public std::streambuf
{
public:
// Somehow store a pointer to to_append.
explicit existing_string_buf(std::string &to_append) :
m_to_append(&to_append){}
virtual int_type overflow (int_type c) {
if (c != EOF) {
m_to_append->push_back(c);
}
return c;
}
virtual std::streamsize xsputn (const char* s, std::streamsize n) {
m_to_append->insert(m_to_append->end(), s, s + n);
return n;
}
private:
std::string *m_to_append;
};
int main()
{
std::string s;
existing_string_buf b(s);
std::ostream o(&b);
o << 22;
std::cout << s << std::endl;
}
You could write a std::string casting operator:
struct X {
int i;
friend std::ostream& operator<<(std::ostream& os, X const& x) {
os << "X(" << x.i << ')';
return os;
}
operator std::string() {
return std::string("X(") + std::to_string(x.i) + ")";
}
};
Then, you could simply append it to a std::string:
X myX;
myX.i = 2;
std::string s("The value is ");
s.append(myX); //myX is cast into the string "X(2)"
In this specific case I'd just follow the KISS principle:
struct X {
int i;
std::string toString() const {
return "X(" + std::to_string(i) + ")";
}
};
Usage:
string += x.toString();
std::cout << x.toString();
An operator<<(std::ostream&, …) isn't really suitable for generic string conversion, so if that's what you're after then a toString type of method / free function is much better. And if you want std::cout << x you can trivially implement operator<< to just call toString.
Since the original string is likely only large enough for the existing allocation, the best you can hope for is to format everything you want to append once in the stream, then append the result as you have in your example.
If you plan on performing these appends often, I would argue std::string is the wrong type for the problem at hand. I would recommend using an std::ostringtream directly instead of a std::string, and only convert to a string when you need the final result.
In C++ there is a standard library function called cout, which lets me send text to the console. I am sure you know that.
#include <iostream>
using std::cout;
cout << "Some Text " << 15 << " Other Text";
To do a linebreak at the end, I need to use endl.
cout << "Some Text " << 15 << " Other Text" << endl;
How can I write a function named coutl which behaves like cout but also adds a likebreak? I want to use the same syntax that cout uses, especially the << operator.
coutl << "Some Text " << 15 << " Other Text"; // coutl should add a linebreak
By creating a little proxy object which adds << endl in its destructor:
class AddEndl
{
public:
AddEndl(std::ostream& os) : _holder(new Holder(os)) {}
template <class T>
friend std::ostream& operator<< (const AddEndl& l, const T& t)
{
return (l._holder->_os) << t;
}
private:
struct Holder {
Holder (std::ostream& os) : _os(os) {}
~Holder () { _os << std::endl; }
std::ostream& _os;
};
mutable std::shared_ptr<Holder> _holder;
}
Then you need a function so that you will get a temporary:
AddEndl wrap(std::ostream& os)
{
return AddEndl(os);
}
This should then work:
wrap(std::cout) << "Hello";
UPDATE:
I move the destructor which adds a std::endl to an inner object owned by a std::shared_ptr<> so that the example doesn't depend on Copy Elision anymore.
Not possible with just a non-temp object created on the stack & which has full function scope. How will the object ever know what this is the last of the chained calls to the << operator?
You can try hacks like these
class coutl
{
public:
~coutl()
{
cout<<endl;
}
template<class T>
coutl &operator<<(const T &x)
{
cout<<x;
return *this;
}
};
int main()
{
coutl()<<"Hello"<<10<<"World";
coutl()<<"Hello"<<20<<"World";
}
Another similar hack using the destructor
class myostream
{
public:
~myostream()
{
cout<<endl;
}
template<class T>
myostream &operator<<(const T &x)
{
cout<<x;
return *this;
}
};
int main()
{
{
myostream coutl;
coutl<<"Hello"<<10<<"World";
}
{
myostream coutl;
coutl<<"Hello"<<10<<"World";
}
}
In fact the code
cout << "Some Text " << 15 << " Other Text" << endl;
calls the operator function(s)
// (pseudo code)
std::ostream& operator<<(std::ostream, [type] obj);
several times for each use of the << operators.
To achieve what you want you would need to create a class that behaves like std::ostream, but 'magically' knows when the 'last' call to operator<< is issued and appends a linebreak. That's not possible IMHO without another object that keeps track of the statements scope.
coutl << "Some Text " << 15 << " Other Text"; // coutl should add a linebreak
Your idea can't be realize. In fact, cout << str1; is equivalent to cout.operator<<(str1) which returns a reference of cout itself. So cout << a << b << c; can be resolvd to ((cout << a) << b) << c; It doesn't know when is the last call to insert an linebreak.
Guys would it be difficult to write coutn which would basically place newline symbol at the end of the input. While working with console (that's all I can do at the moment) I'm finding very tedious to write '\n' every time I want the line to be a new line.
Or maybe it is already implemented?
To circumvent the multiple injections on a single line, you could use a temporary object. This temporary object would add the '\n' in its destructor.
struct coutn {
coutn(): os(cout) {}
~coutn() { os << '\n'; }
template <typename T>
coutn & operator<<(T const & x) { os << x; return *this; }
private:
ostream &os;
};
coutn() << "Hello " << "World" << "!";
In the end, I'm wondering if this coutn is actually better?
Well, the first obvious thing would be to implement some kind of wrapper around it:
class Print
{
public:
explicit Print(std::ostream& stream = std::cout): mStream(stream) {}
~Print() { mStream << '\n'; }
template <class T>
Print& operator<<(T const& t) { mStream << t; return *this; }
private:
std::ostream& mStream;
};
Usage is like such:
int main(int argc, char* argv[])
{
Object object;
Print() << "My new object value: " << object;
std::ofstream file("file.log");
Print(file) << "My new object value: " << object;
}
Easy, Peasy.
Roughly:
struct StreamFilterN
{
ostream & os;
StreamFilterN(ostream & os_) : os(os_) {}
template <typename T>
StreamFilterN & operator<<(T const & x) { os << x << "\n"; return *this; }
}
StreamFilterN coutn(cout);
coutn << "Hello world";
coutn << "Yeah, like.";
(I'm not sure if this works perfectly, but it should get you started)
The way that streams work is that they add one thing and then return itself.
so are you sure you'd want to do what you're asking?
For example:
s << "a" << "b";
Would put:
a
b
Surely you can find a way with some kind of wrapper but the extra overhead incurred and the diminished code readability I don't think is worth it. Most coders are familiar with standard C++. Most coders are not familiar with your coutn and how it works.
Come one people. You must admit that C++'s newlines are too verbose. Look at C#, D, Java, Python, Ruby, should I go on? I don't think you should implement a coutn. I think you'd be better off following D's example with write, writeln, writef, and writefln variadic template functions.
Anyway here is how to do it without macros and with out needing to explicitly create temporaries.
class coutn_t
{
private:
class newliner
{
public:
explicit newliner(std::ostream & out=std::cout) : m_out(out) { }
template<typename T>
newliner& operator<<( const T& t)
{
m_out << t;
return *this;
}
~newliner() { m_out << std::endl; }
private:
std::ostream & m_out;
};
public:
// NOTE: these return by value. Only one newliner will be
// destructed however as RVO will eliminate the copy.
newliner operator()( std::ostream& out )
{ return newliner(out); }
template< typename T >
newliner operator<<( const T& t )
{
std::cout << t;
return newliner(std::cout);
}
};
coutn_t coutn;
coutn << "Hello World!";
coutn << "Hello " << "World" << '!';
std::ofstream file("ouput.txt");
coutn(file) << "Hello World" << " via file";
The complete solution will have to add more overloads for operator<< to handle stream manipulators (std::hex etc). The functions returning newliners must always be inline to allow RVO.
I have a C++ class MyObject and I want to be able to feed this data like I would to a osstream (but unlike a direct sstream, have the incoming data be formatted a special way). I can't seem to figure out how to overload a operator for MyObject to eat input given to it.
class MyObject {
public:
ostringstream s;
FEEDME
};
int main() {
MyObject obj;
obj.FEEDME << "Hello" << 12345;
// I want obj.s == ":Hello::12345:"
}
I want it so every item fed in be surrounded by : :
So in the given example, s = ":Hello::12345" should be the final outcome. What my question is, how can I tell the object that when ever a <<something, put : : around the something.
Is this possible?
try this:
class MyObject {
public:
template <class T>
MyObject &operator<<(const T &x) {
s << ':' << x << ':';
return *this;
}
std::string to_string() const { return s.str(); }
private:
std::ostringstream s;
};
MyObject obj;
obj << "Hello" << 12345;
std::cout << obj.to_string() << std::endl;
There are certain things you won't be able to shove into the stream, but it should work for all the basics.
You may find the answers for How do I create my own ostream/streambuf? helpful.
I would take a slightly different approach and create a formater object.
The formater object would then handle the inserting of format character when it is applied to a stream.
#include <iostream>
template<typename T>
class Format
{
public:
Format(T const& d):m_data(d) {}
private:
template<typename Y>
friend std::ostream& operator<<(std::ostream& str,Format<Y> const& data);
T const& m_data;
};
template<typename T>
Format<T> make_Format(T const& data) {return Format<T>(data);}
template<typename T>
std::ostream& operator<<(std::ostream& str,Format<T> const& data)
{
str << ":" << data.m_data << ":";
}
int main()
{
std::cout << make_Format("Hello") << make_Format(123);
}