I need to overload the << operator for streams to work with built-in types. For strings it's not a problem, since I simply overload the function like this:
ostream& operator<<(ostream& os, const char* str) { /*...*/ }
This works because this function is global, not a member. The problem is that I need to overload the << operator for other primitive types (ints, floats, etc) but those are member functions. Is there a way I can do this? I need it to work with not only cout but other streams as well. Thanks in advance.
You shouldn't try to change what the operator in std::cout << 3; does. It's part of a standard API. If you need to output in some format which stream manipulators can't support, then for example you could write a little wrapper:
struct MyFormatter {
MyFormatter (ostream &o) : o(o) {}
ostream &o;
};
MyFormatter &operator<<(MyFormatter &mf, int i) {
mf.o << "int(" << i << ")"; // or whatever
return mf;
}
Then use it like this:
MyFormatter mf(std::cout);
mf << 1 << "," << 2 << "," << 3;
In C++, operator overloads require at least one operand of a "class type" or enumeration type.
The point is you are not allowed to overload operator for primitive types.
http://www.parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.10
Related
I'd like to know how do stream classes work in C++. When you say:
cout<<"Hello\n";
What does exactly do "<<". I know that cout is an object form iostream that represents the standard output stream oriented to narrow characters (char).
In C "<<" is the bitwise shift operator so it moves bits to the left but in C++ it's and insertion operator. Well, that's all I know, I don't really understand how does this work under the hood.
What I'm asking for is detailed explanation about stream classes in C++, how they are defined and implemented.
Thank you very much for your time and sorry for my English.
Let's create a class that looks like cout (but without as many bells and whistles).
#include <string>
class os_t {
public:
os_t & operator<<(std::string const & s) {
printf("%s", s.c_str());
return *this;
}
};
int main() {
os_t os;
os << "hello\n";
os << "chaining " << "works too." << "\n";
}
Notes:
operator<< is an operator overload just like operator+ or all of the other operators.
Chaining works because we return ourselves: return *this;.
What if you can't change the os_t class because someone else wrote it?
We don't have to use member functions to define this functionality. We can also use free functions. Let's show that as well:
#include <string>
class os_t {
public:
os_t & operator<<(std::string const & s) {
printf("%s", s.c_str());
return *this;
}
};
os_t & operator<<(os_t & os, int x) {
printf("%d", x);
return os;
// We could also have used the class's functionality to do this:
// os << std::to_string(x);
// return os;
}
int main() {
os_t os;
os << "now we can also print integers: " << 3 << "\n";
}
Where else is operator overloading useful?
A great example of how this kind of logic is useful can be found in the GMP library. This library is designed to allow arbitrarily large integers. We do this, by using a custom class. Here's an example of it's use. Note that operator overloading let's us write code that looks almost identical to if we were using the traditional int type.
#include <iostream>
#include <gmpxx.h>
int main() {
mpz_class x("7612058254738945");
mpz_class y("9263591128439081");
x = x + y * y;
y = x << 2;
std::cout << x + y << std::endl;
}
<< is a binary operator in C++, and thus can be overloaded.
You know of the C usage of this operator, where 1 << 3 is a binary operation returning 8. You could think of this as the method int operator<<(int, int) where passing in arguments 1 and 3 returns 8.
Technically, operator<< could do anything. It's just an arbitrary method call.
By convention in C++, the << operator is used for handling streams in addition to being the bit-shift operator. When you perform cout << "Hello!", you are calling a method with prototype ostream & operator<< (ostream & output, char const * stream_me). Note the return value ostream &. That return allows you to call the method multiple times, like std::cout << "Hello World" << "!"; which is calling operator<< twice... once on std::cout and "Hello World", and the second time on the result of that first invocation and "!".
In general, if you were to create a class named class Foo, and you wanted it to be printable, you could define your printing method as ostream & operator<< (ostream & output, Foo const & print_me). Here is a simple example.
#include <iostream>
struct Circle {
float x, y;
float radius;
};
std::ostream & operator<< (std::ostream & output, Circle const & print_me) {
output << "A circle at (" << print_me.x << ", " << print_me.y << ") with radius " << print_me.radius << ".";
}
int main (void) {
Circle my_circle;
my_circle.x = 5;
my_circle.y = 10;
my_circle.radius = 20;
std::cout << my_circle << '\n';
return 0;
}
Operators can be considered functions with syntactic sugar that allow for clean syntax. This is simply a case of operator overloading.
I've come across functions that, rather than overloading the operator << to use with cout, declare a function that takes an ostream and returns an ostream
Example:
#include <iostream>
class A {
private:
int number;
public:
A(int n) : number(n) {}
~A() {}
std::ostream& print(std::ostream& os) const;
friend std::ostream& operator<<(std::ostream& os, const A a);
};
An example of implementation:
std::ostream& A::print(std::ostream& os) const {
os << "number " << number;
return os;
}
std::ostream& operator<<(std::ostream& os, const A a) {
os << "number " << a.number;
return os;
}
Now if I run this I can use the different functions in different situations.. E.g.
int main() {
A a(1);
std::cout << "Object."; a.print(std::cout);
std::cout << "\n\n";
std::cout << "Object." << a;
std::cout << "\n\n";
return 0;
}
Output:
Object.number 1
Object.number 1
There doesn't seem to be a situation where the print function would be needed since you could only use separately or in the beginning of a "cout chain" but never in the middle or end of it which perhaps makes it useless. Wouldn't it (if no other use is found) be better off using a function "void print()" instead?
It would make sense where an inheritance hierarchy comes in to play. You can make the print method virtual, and in the operator for the base class, delegate to the virtual method to print.
It would make a lot more sense if operator<<() actually looked like
std::ostream& operator<<(std::ostream& os, const A a) {
return a.print(os);
}
Then operator<<() wouldn't need to be a friend.
A function that can be used as the start of a cout chain certainly sounds more useful than one that can't, all other things being equal.
I've implemented several functions with signatures like you describe because operator<< is only one name, and sometimes I need to have objects streamed in multiple different ways. I have one format for printing to the screen, and another format for saving to a file. Using << for both would be non-trivial, but choosing a human-readable name for at least one of the operations is easy.
The use of operator<< assumes that there is only one sensible way to print data. And sometimes that is true. But sometimes there are multiple valid ways to want to output data:
#include <iostream>
using std::cout; using std::endl;
int main()
{
const char* strPtr = "what's my address?";
const void* address = strPtr;
// When you stream a pointer, you get the address:
cout << "Address: " << address << endl;
// Except when you don't:
cout << "Not the address: " << strPtr << endl;
}
http://codepad.org/ip3OqvYq
In this case, you can either chose one of the ways as the way, and have other functions (print?) for the rest. Or you can just use print for all of them. (Or you might use stream flags to trigger which behavior you want, but that's harder to set up and use consistently.)
I am trying to write a simple audit class that takes input via operator << and writes the audit after receiving a custom manipulator like this:
class CAudit
{
public:
//needs to be templated
CAudit& operator << ( LPCSTR data ) {
audittext << data;
return *this;
}
//attempted manipulator
static CAudit& write(CAudit& audit) {
//write contents of audittext to audit and clear it
return audit;
}
private:
std::stringstream audittext;
};
//to be used like
CAudit audit;
audit << "Data " << data << " received at " << time << CAudit::write;
I recognise that the overloaded operator in my code does not return a stream object but was wondering if it was still possible to use a manipulator like syntax. Currently the compiler is seeing the '<<' as the binary right shift operator.
Thanks for any input,
Patrick
To make it work you have to add overload of operator << for functions,
than call the function from it:
class CAudit
{
//...other details here as in original question
CAudit& operator << (CAudit & (*func)(CAudit &))
{
return func(*this);
}
};
CAudit audit;
audit << "some text" << CAudit::write;
Binary shift operator and stream operator is the same operator. It is completely legal to overload operator+ for your class to write "Hello world" on std::cout (although it is a very bad idea). The same way C++ standard authors decided to overload operator<< for streams as writing to the stream.
You didn't write clearly what is your problem. My guess is compilation error. The best thing in this case is to quote the error message. If I am right, the problem is, that you defined only operator<< for LPCSTR, and then you want it to work function object on the right side.
You use word "manipulator", but you misunderstand something. Manipulator for a stream (stream from STL) is a function that performs some actions on the stream it is written to. And it works only because of this overload:
ostream& operator<< (ostream& ( *pf )(ostream&));
which takes a function and applies it to a stream.
Similarly you need:
CAudit& operator<< (CAudit& ( *pf )(CAudit& audit))
{
return (*pf)(audit);
}
Wouldn't this
class CAudit
{
public:
template< typename T >
CAudit& operator<<( const T& data )
{
audittext << data;
return *this;
}
class write {};
void operator<<( const write& data )
{
/* whatever */
}
private:
std::stringstream audittext;
};
do what you want?
I do something very similar for tracing, but use a stringstream. This ensures that all 3rd party operator << () and manipulators work. I also use the desctructor instead of the customer write manipulator.
class DebugStream
{
public:
DebugStream(short level, const char * file, int line) {
sstream << "L" << level << "\t" << file << "\t" << line << "\t";
}
~DebugStream() { write(sstream.str()); }
std::ostream & stream() { return sstream; }
private:
std::stringstream sstream;
DebugStream(const DebugStream &);
DebugStream & operator=(const DebugStream &);
};
This is then made available with some macros:
#define DBG_ERROR if (1<=dbg_level()) DebugStream(1, __FILE__, __LINE__).stream()
#define DBG_INFO if (2<=dbg_level()) DebugStream(2, __FILE__, __LINE__).stream()
And the code just uses the macros
DBG_INFO << "print some debug information";
You don't need a specific write manipulator to flush the data to the log file. When the anonymous DebugStream object goes out of scope (once control leaves the line) the the contents are automatically written.
Although I usually avoid macros in this case the use of the if statement means you don't have the overhead of building the trace line unless you actually require it.
Returning the ostream via the stream() method enables this to work for global member functions, as anonymous objects cannot be passed as non-const reference parameters.
I overloaded operator <<
template <Typename T>
UIStream& operator<<(const T);
UIStream my_stream;
my_stream << 10 << " heads";
Works but:
my_stream << endl;
Gives compilation error:
error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'UIStream' (or there is no acceptable conversion)
What is the work around for making my_stream << endl work?
std::endl is a function and std::cout utilizes it by implementing operator<< to take a function pointer with the same signature as std::endl.
In there, it calls the function, and forwards the return value.
Here is a code example:
#include <iostream>
struct MyStream
{
template <typename T>
MyStream& operator<<(const T& x)
{
std::cout << x;
return *this;
}
// function that takes a custom stream, and returns it
typedef MyStream& (*MyStreamManipulator)(MyStream&);
// take in a function with the custom signature
MyStream& operator<<(MyStreamManipulator manip)
{
// call the function, and return it's value
return manip(*this);
}
// define the custom endl for this stream.
// note how it matches the `MyStreamManipulator`
// function signature
static MyStream& endl(MyStream& stream)
{
// print a new line
std::cout << std::endl;
// do other stuff with the stream
// std::cout, for example, will flush the stream
stream << "Called MyStream::endl!" << std::endl;
return stream;
}
// this is the type of std::cout
typedef std::basic_ostream<char, std::char_traits<char> > CoutType;
// this is the function signature of std::endl
typedef CoutType& (*StandardEndLine)(CoutType&);
// define an operator<< to take in std::endl
MyStream& operator<<(StandardEndLine manip)
{
// call the function, but we cannot return it's value
manip(std::cout);
return *this;
}
};
int main(void)
{
MyStream stream;
stream << 10 << " faces.";
stream << MyStream::endl;
stream << std::endl;
return 0;
}
Hopefully this gives you a better idea of how these things work.
The problem is that std::endl is a function template, as your operator <<
is. So when you write:
my_stream << endl;
you'll like the compiler to deduce the template parameters for the operator
as well as for endl. This isn't possible.
So you have to write additional, non template, overloads of operator << to
work with manipulators. Their prototype will look like:
UIStream& operator<<(UIStream& os, std::ostream& (*pf)(std::ostream&));
(there are two others, replacing std::ostream by std::basic_ios<char> and
std::ios_base, which you have also to provide if you want to allow all
manipulators) and their implementation will be very similar to the one of
your templates. In fact, so similar that you can use your template for
implementation like this:
typedef std::ostream& (*ostream_manipulator)(std::ostream&);
UIStream& operator<<(UIStream& os, ostream_manipulator pf)
{
return operator<< <ostream_manipulator> (os, pf);
}
A final note, often writing a custom streambuf is often a better way to
achieve what one try to achieve applying to technique you are using.
I did this to solve my problem, here is part of my code:
template<typename T>
CFileLogger &operator <<(const T value)
{
(*this).logFile << value;
return *this;
}
CFileLogger &operator <<(std::ostream& (*os)(std::ostream&))
{
(*this).logFile << os;
return *this;
}
Main.cpp
int main(){
CFileLogger log();
log << "[WARNINGS] " << 10 << std::endl;
log << "[ERRORS] " << 2 << std::endl;
...
}
I got the reference in here http://www.cplusplus.com/forum/general/49590/
Hope this can help someone.
See here for better ways of extending IOStreams. (A bit outdated, and tailored for VC 6, so you will have to take it with a grain of salt)
The point is that to make functors work (and endl, which both outputs "\n" and flushes is a functor) you need to implement the full ostream interface.
The std streams are not designed to be subclassed as they have no virtual methods so I don't think you'll get too far with that. You can try aggregating a std::ostream to do the work though.
To make endl work you need to implement a version of operator<< that takes a pointer-to-function as that is how the manipulators such as endl are handled i.e.
UStream& operator<<( UStream&, UStream& (*f)( UStream& ) );
or
UStream& UStream::operator<<( UStream& (*f)( UStream& ) );
Now std::endl is a function that takes and returns a reference to a std::basic_ostream so that won't work directly with your stream so you'll need to make your own version which calls through to the std::endl version in your aggregated std::iostream.
Edit: Looks likes GMan's answer is better. He gets std::endl working too!
In addition to the accepted answer, with C++11 it is possible to overload operator<< for the type:
decltype(std::endl<char, std::char_traits<char>>)
Hey. Is it possible to overload operator<< for primitive types? Fx lets say that I want to write a std::endl each time want to write a int. Can I overload operator<< for int, so that it automatic puts a std::endl to the output? I have tried with this,
std::ostream& operator<<(std::ostream& strm, int & i)
{
strm << i << std::endl;
return strm;
}
but it doesn't work. I cant recall the compiler error message, but I think that I'm getting operator overloading all wrong any ways.
I try to call the above overloaded operator<< in this way,
int main()
{
int i = 2;
std::out<<"Here is an int " << i;
return 0;
}
But it doesn't work at all. Maybe I can't overload POD types?
As zabzonk said, the standard library provides an (ostream&, int) overload so you can't define another.
To simulate what you were doing (though it is completely pointless in its present form :) :
class EndlinedInteger {
public:
EndlinedInteger(int i) : i(i) { }
friend ostream& operator<<(ostream&, EndlinedInteger const&);
private:
int i;
};
ostream& operator<<(ostream& out, EndlinedInteger const& ei) {
out << ei.i << endl;
return out;
}
int main()
{
EndlinedInteger i = 2;
std::cout<<"Here is an int " << i;
}
Remember that here you use << operator not only on int but also on ostream. You could derive from ostream and implement it in your own derived class, but I would suggest to make a simple macro like
#define EL(i) (i)<<std::endl
Alternatively you could make boxed int class and override the << for standard ostream and boxed int (like in answer by Iraimbilanja) class. Sounds like huge overkill but could work.
Your problem is that there is already an overload for operator << (ostream &, int), the one supplied by the C++ standard library. If you remove the overload definition and use:
#include <iostream>
int main()
{
int i = 2;
std::out<<"Here is an int " << i;
return 0;
}
things work as expected.
And BTW, compiler error messages are kind of important, so it's a good idea to remember them and quote them in posts when asking questions.
edit - std::out above should of couse be std::cout