I'm trying to write my own logging class and use it as a stream:
logger L;
L << "whatever" << std::endl;
This is the code I started with:
#include <iostream>
using namespace std;
class logger{
public:
template <typename T>
friend logger& operator <<(logger& log, const T& value);
};
template <typename T>
logger& operator <<(logger& log, T const & value) {
// Here I'd output the values to a file and stdout, etc.
cout << value;
return log;
}
int main(int argc, char *argv[])
{
logger L;
L << "hello" << '\n' ; // This works
L << "bye" << "alo" << endl; // This doesn't work
return 0;
}
But I was getting an error when trying to compile, saying that there was no definition for operator<< (when using std::endl):
pruebaLog.cpp:31: error: no match for ‘operator<<’ in ‘operator<< [with T = char [4]](((logger&)((logger*)operator<< [with T = char [4]](((logger&)(& L)), ((const char (&)[4])"bye")))), ((const char (&)[4])"alo")) << std::endl’
So, I've been trying to overload operator<< to accept this kind of streams, but it's driving me mad. I don't know how to do it. I've been loking at, for instance, the definition of std::endl at the ostream header file and written a function with this header:
logger& operator <<(logger& log, const basic_ostream<char,char_traits<char> >& (*s)(basic_ostream<char,char_traits<char> >&))
But no luck. I've tried the same using templates instead of directly using char, and also tried simply using "const ostream& os", and nothing.
Another thing that bugs me is that, in the error output, the first argument for operator<< changes, sometimes it's a reference to a pointer, sometimes looks like a double reference...
endl is a strange beast. It isn't a constant value. It's actually, of all things, a function. You need a special override to handle the application of endl:
logger& operator<< (logger& log, ostream& (*pf) (ostream&))
{
cout << pf;
return log;
}
This accepts insertion of a function that takes an ostream reference and returns an ostream reference. That's what endl is.
Edit: In response to FranticPedantic's interesting question of "why can't the compiler deduce this automatically?". The reason is that if you delve yet deeper, endl is actually itself a template function. It's defined as:
template <class charT, class traits>
basic_ostream<charT,traits>& endl ( basic_ostream<charT,traits>& os );
That is, it can take any sort of ostream as its input and output. So the problem isn't that the compiler can't deduce that T const & could be a function pointer, but that it can't figure out which endl you meant to pass in. The templated version of operator<< presented in the question would accept a pointer to any function as its second argument, but at the same time, the endl template represents an infinite set of potential functions, so the compiler can't do anything meaningful there.
Providing the special overload of the operator<< whose second argument matches a specific instantiation of the endl template allows the call to resolve.
endl is an IO manipulator, which is a functor that accepts a stream by reference, performs some operation on it, and returns that stream, also by reference. cout << endl is equivalent to cout << '\n' << flush, where flush is a manipulator that flushes the output buffer.
In your class, you just need to write an overload for this operator:
logger& operator<<(logger&(*function)(logger&)) {
return function(*this);
}
Where logger&(*)(logger&) is the type of a function accepting and returning a logger by reference. To write your own manipulators, just write a function that matches that signature, and have it perform some operation on the stream:
logger& newline(logger& L) {
return L << '\n';
}
I believe that the problem is your stream doesn't overload operator<< to accept a function that has the same type as std::endl as illustrated in this answer: std::endl is of unknown type when overloading operator<<
In C++ it is the stream buffer that encapsulates the underlying I/O mechanisim. The stream itself only encapsulates the conversions to string, and the I/O direction.
Thus you should be using one of the predefined stream classes, rather than making your own. If you have a new target you want your I/O to go to (like a system log), what you should be creating is your own stream buffer (derived from std::streambuf).
Related
I was working on a function which looks like so:
inline std::ostream& mvUp(int n,std::ostream& ss){
char u[8];
sprintf(u,"\033[%dA",n);
ss<<u;
return ss;
}
and using it like so:
std::cout<<mvUp(1);
however it shows error:
std::cout<<mvUp(1);
| ^_____too few args in function call
^_______________no operator "<<" match these operands
I also tried: std::cout<<mvUp(1,std::cout); but still not working.
std::cout<<mvUp(1);
^_______________no operator "<<" match these operands
now when I try making it template,
template <int n>
inline std::ostream& mvUp(std::ostream& ss){
char u[8];
sprintf(u,"\033[%dA",n);
ss<<u;
return ss;
}
and use it: std::cout<<mvUp<1>, this works totally fine but the problem with this is that templates take const args.
Not able to figure out where am I getting wrong. Also how is it working in templates when I am not passing any args?
Modern C++ code uses std::string, and other classes. This makes implementing this kind of an overload trivial.
#include <string>
#include <sstream>
inline std::string mvUp(int n) {
std::ostringstream o;
o << "\033[" << n << "A";
return o.str();
}
Then, everything will work automatically:
std::cout<<mvUp(1);
Your mvUp returns std::string, and the existing << overload takes care of the rest.
The fact that std::ostream& mvUp(std::ostream& ss); std::cout << mvUp<1> works is not a peculiarity of C++ function call syntax.
std::cout has its operator<< overloaded to accept single-parameter functions like this one, and call them by passing itself as the first argument.
Given std::ostream& mvUp(int n,std::ostream& ss);, std::cout<<mvUp(1) doesn't work because your function doesn't have one parameter. And std::cout << mvUp(1,std::cout); doesn't work because your function returns std::ostream&, which can't be printed.
The generic solution is to make a class with overloaded operator<<. But, as the other answer suggests, here you can just make a function that returns std::string, and print its return value.
You are trying to create a custom ostream manipulator, similar to std::setw() and other manipulators from the <iomanip> library. But what you have written is not the correct way to implement that. Your manipulator needs to return a type that holds the information you want to manipulate the stream with, and then you need to overload operator<< to stream out that type. That will give you access to the ostream which you can then manipulate as needed.
Try something more like this:
struct mvUpS
{
int n;
};
mvUpS mvUp(int n) {
return mvUpS{n};
}
std::ostream& operator<<(std::ostream& ss, const mvUpS &s) {
return ss << "\033[" << s.n << "A";
}
Now std::cout << mvUp(1); will work as expected.
Demo
I have the following code:
#include <iostream>
using namespace std;
ostream& f(ostream& os) {
return os << "hi";
}
int main() {
cout << "hello " << f << endl;
return 0;
}
And somehow this works - the output is "hello hi". How does this get interpreted by the compiler? I don't understand how a function can be inserted into a stream.
std::ostream has an operator<< overload that receives a pointer to a function with the signature such as the one you wrote (number 11 in this list):
basic_ostream& operator<<(
std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) );
which just calls the given function passing itself as argument. This overload (along with several similar others) is there to allow you to implement stream manipulators, i.e. stuff that you output in the stream with an << and changes the state of the stream from there. For example, our version of the (incorrectly) ubiquitous std::endl may be implemented as
std::ostream &myendl(std::ostream &s) {
s<<'\n';
s.flush();
return s;
}
which can then be used exactly as the "regular" std::endl:
std::cout<<"Hello, World!"<<myendl;
(the actual implementation is templated and a bit more complicated because it has to work even with wide streams, but you got the idea)
std::ostream::operator<< has an overload which accepts a function as parameter; and the body of that overload is to invoke the function given.
This is exactly how endl works in fact. endl is actually a function similar to:
ostream &endl(ostream &os)
{
os << '\n';
os.flush();
return os;
}
I don't understand what this ostream function declaration means:
ostream& operator<< (ostream& (*pf)(ostream&));
(specifically, the (*pf)(ostream&) part). I want to do something like:
void print(ostream& os){
cout << os;
}
but I get the error:
Invalid operands to binary expression ('ostream' . . . and 'ostream')
I don't understand what this ostream function declaration means:
ostream& operator<< (ostream& (*pf)(ostream&));
Have you seen functions like std::endl, std::flush, std::hex, std::dec, std::setw...? They can all be "sent" to a stream using "<<", then they get called with the stream as a function argument and do their magic on the stream. They actually match the ostream& (*pf)(ostream&) argument above, and that operator's the one that lets them be used. If we look at the Visual C++ implementation...
_Myt& operator<<(_Myt& (__cdecl *_Pfn)(_Myt&))
{
return ((*_Pfn)(*this));
}
...you can see if just calls the function, passing the stream it's used on as an argument. The functions are expected to return a reference to the same stream argument, so that further << operations may be chained, or the stream may be implicitly converted to bool as a test of stream state.
See http://en.cppreference.com/w/cpp/io/manip for more information about io manipulators.
You wanted help with:
void print(ostream& os){
cout << os;
}
The issue here is that you're sending the ostream argument to another stream - cout - and it doesn't know what you want it to do with it.
To send the current content of os to cout, try:
void print(ostream& os){
cout << os.rdbuf();
}
Or if you want to print some actual data to the stream represented by the argument:
void print(ostream& os){
os << "show this!\n";
}
print(std::cout); // to write "show this!\n" to `std::cout`
print(std::cerr); // to write "show this!\n" to `std::cerr`
What the declaration means.
The formal argument …
ostream& (*pf)(ostream&)
declares an argument named pf which is a pointer, to which you can apply an argument parenthesis with an ostream& argument, which constitutes a call that returns an ostream& as its result.
It can be simplified to just …
ostream& pf(ostream&)
where you can more easily see that it's a function.
The drawback is that this form is seldom used, so not everybody is aware that it decays to the first form (much the same as e.g. int x[43] as a formal argument type is effectively the same as just int x[] because both these forms decay to just int* x in the function type, so that in the function body you can even increment that x).
What it’s used for.
A function of the above form is usually an output stream manipulator. That means, you can pass it to the << output operator. What happens then is just that << calls that function, with the stream as argument, as specified by C++11 §27.7.3.6.3/1 and 2:
basic_ostream<charT,traits>& operator<<
(basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&))
Effects: None. Does not behave as a formatted output function (as described in 27.7.3.6.1).
Returns: pf(*this).
There is also an overload of << that takes a similar function, but with std::basic_ios& argument and result, and one that takes a function with std::ios_base argument and result.
Class std::ios_base is the base of the iostreams class hierarchy and the standard manipulators defined at that level are …:
Format flag manipulators:
boolalpha, noboolalpha, showbase, noshowbase, showpoint, noshowpoint, showpos, noshowpos, skipws, noskipws, uppercase, nouppercase, unitbut and nounitbuf.
Adjustment field manipulators:
internal, left and right.
Numeral system base manipulators:
dec, hex and oct.
Floating point number presentation manipulators:
fixed, scientific, hexfloat and defaultfloat.
Manipulators that take user arguments don’t follow this form and those that the standard provides are in a separate header called <iomanip>.
Example: a user-defined manipulator.
Code:
#include <iostream>
#include <string>
// With Visual C++, if necessary define __func__ as __FUNCTION__.
using namespace std;
class Logger
{
private:
string funcname_;
static int call_level;
auto
static indent( ostream& stream )
-> ostream&
{ return (stream << string( 4*call_level, ' ' )); }
public:
Logger( string const& funcname )
: funcname_( funcname )
{
clog << indent << "-> " << funcname_ << endl;
++call_level;
}
~Logger()
{
--call_level;
clog << indent << "<- " << funcname_ << endl;
}
};
int Logger::call_level = 0;
#define WITH_LOGGING Logger logging( __func__ )
void c() { WITH_LOGGING; }
void b() { WITH_LOGGING; c(); }
void a() { WITH_LOGGING; b(); }
auto main() -> int { a(); }
Output, which shows the calls and returns, nicely indented:
-> a
-> b
-> c
<- c
<- b
<- a
The parameter portion of the declaration:
ostream& operator<< (ostream& (*pf)(ostream&));
is a function pointer syntax.
The expression:
ostream& (*pf)(ostream&)
Declares a pointer to a function, pf, that takes an ostream& parameter and returns a reference to an ostream.
If I declare a function:
ostream& my_function(ostream& output);
Then I can pass a pointer to the function as the parameter:
operator<< (my_function);
Read up on function pointer syntax. Search the web and stackoverflow.
How do I write user-defined stream manipulators in C++ that control the format of streaming a self-written class?
Specifically, how would I write simple manipulators verbose and terse to control the amount of output streamed?
My environment is GCC, versions 4.5.1 and up.
Example:
class A
{
...
};
A a;
// definition of manipulators verbose and terse
cout << verbose << a << endl; // outputs a verbosely
cout << terse << a << endl; // outputs a tersely
PS: What follows is just a side question, feel free to ignore it: Can this portably be extended to manipulators taking arguments? Josuttis writes in "The C++ Standard Library" near the end of section 13.6.1 that writing manipulators taking argument is implementation dependent. Is this still true?
I don't see any reason for them to be implementation dependent.
This is comething that I use, for the actual manipulator, create a function that returns an instance of the following helper. If you need to store the data, just store it inside the helper, some global variable, singleton, etc...
/// One argument manipulators helper
template < typename ParType >
class OneArgManip
{
ParType par;
std::ostream& (*impl)(std::ostream&, const ParType&);
public:
OneArgManip(std::ostream& (*code)(std::ostream&, const ParType&), ParType p)
: par(p), impl(code) {}
// calls the implementation
void operator()(std::ostream& stream) const
{ impl(stream,par); }
// a wrapper that allows us to use the manipulator directly
friend std::ostream& operator << (std::ostream& stream,
const OneArgManip<ParType>& manip)
{ manip(stream); return stream; }
};
Example of a manipulator based on this:
OneArgManip<unsigned> cursorMoveUp(unsigned c)
{ return OneArgManip<unsigned>(cursorMoveUpI,c); }
std::ostream& cursorMoveUpI(std::ostream& stream, const unsigned& c)
{ stream << "\033[" << c << "A"; return stream; }
For some explanation:
u use the manipulator, that returns a new instance of the helper bound to an implementation of the helper
stream tries to process the helper, that invokes the << overload on the helper
that invokes the () operator on the helper
that invokes the real implementation of the helper with the parameter passed from the original manipulator call
If you want I can post 2 param and 3 param helpers as well. The principle is the same though.
i need someone who explain me these lines of code part by part and i need some help in using "ostream" with simple examples. thank you :).
inline std::ostream& operator<<(std::ostream& os, const Telegram& t)
{
os << "time: " << t.DispatchTime << " Sender: " << t.Sender
<< " Receiver: " << t.Receiver << " Msg: " << t.Msg;
return os;
}
UPDATE 1: when i use this function it doesnt compile and the error says:
std::ostream& class::operator<<(std::ostream& os, const Telegram& t) must take exactly one argument
These line are simply adding the ability to handle Telegram objects to the standard output stream class.
When you add a new class and you want output streams like cout to intelligently handle them, you need to add a new << operator method which has the new object type as the second argument.
What the code above is doing is exactly that. When you later execute the statements:
Telegram tg("Bob", "Hello, how are you?");
cout << tg;
that function in your question will be called with the stream as the first argument and your tg object as the second argument and it will then be able to output the data in a format suitable to the class.
This was actually one of the early C++ things I had trouble getting my head around. Although the class is supposed to be self-contained, you're actually adding something to a different class to handle the output. Once you understand why this is happening (because it's the ostream class that is responsible for outputting things rather than your own class), it will hopefully make sense.
Hopefully making it clearer with a simpler example:
1 inline std::ostream& operator<<(std::ostream& os, const Telegram& t) {
2 os << "message: " << t.Msg;
3 return os;
4 }
Line 1 is simply the function definition. It allows you to return the stream itself (that you pass in) so you can chain << segments. The operator<< is simply the function you're providing, which is the one called when you put << tg into an output stream statement.
Line 2 uses more basic << statements that have already been defined (in this case, whatever type Msg is, probably a string).
Then line 3 returns the stream, again to allow chaining of << segments.
The basic idea is to provide operator<< functions that build on existing operator<< function for the data types that constitute your type.
And with a simple wrapper class containing just an int:
#include <iostream>
// This is my simple class.
class intWrapper {
public:
intWrapper (int x) { myInt = x; };
int getInt (void) { return myInt; }
private:
int myInt;
// Must be friend to access private members.
friend std::ostream& operator<< (std::ostream&, const intWrapper&);
};
// The actual output function.
inline std::ostream& operator<< (std::ostream& os, const intWrapper& t) {
os << "int: " << t.myInt;
return os;
}
// Main program for testing.
// Output with getter and with ostream.
int main (void) {
class intWrapper x(7);
std::cout << x.getInt() << std::endl; // ostream already knows about int.
std::cout << x << std::endl; // And also intWrapper, due to the
// function declared above.
return 0;
}
This outputs:
7
int: 7
the first by just calling the getter function to retrieve the integer, the second by calling the << operator function we added to ostream.
The function you posted (henceforth "the function") is an overload of the insertion operator, operator <<. It allows you to output an object of type Telegram, or any other type deriving from Telegram or convertible to a Telegram, to an output stream. This is similar in spirit to the common use of IO streams in C++:
std::cout << 0 << '\n';
Here you output the int 0 followed by the char newline to the standard output stream. With the function you posted you can now do something like
Telegram tel; // if Telegram has a default constructor
std::cout << tel << '\n';
something you would otherwise not been able to do, because the standard C++ library doesn't know about your new Telegram type and so never defined how to output objects of this type.
In code:
inline std::ostream& operator<<(std::ostream& os, const Telegram& t)
The first line starts with the inline keyword. Presumably the function is defined in a header file, and so in that case you must use the inline keyword so the definition does not violate the one definition rule.
That is, every time you include the header in an implementation file you get the function defined for that implementation file. When the linker comes in to link together all the compiled object files it will find multiple definitions of the function, one in each implementation file that included the header with the function you posted. This is something C++ forbids; C++ demands a function may be implemented no more than one time, and exactly one time if you intend to call it.
The use of the inline keyword essentially asks the C++ compiler to make sure that function is not defined more than once in such a way that the linker jumps off its seat and complains about the ambiguity of multiple definitions to choose from.
Here I argue it's a bad idea to inline the function. It would be a better idea to remove the inline keyword and move the function definition to its own translation unit, or implementation file. This way the function will compile exactly once, as opposed to once for each implementation file that includes the header with the function.
Next you will notice that function is a free function, as opposed to a member function. This allows (requires, as a matter of fact) the function to specify the operator's left operand, the stream object. This means the function will work with any object that is convertible to a stream. It also means you don't need to modify a class to add this extension to output semantics. If the function would be a member then you'd have to change the header of the class, which in turns means recompiling all implementation files that include that header. Granted, it appears your function is defined in a header; that's probably a bad idea, as I explained above.
Next you see that the function returns a std::ostream. std::ostream is in fact typedef'd as std::basic_ostream<char, std::char_traits<char> >, and therefore your function can only output Telegram objects to streams that work on char types.
The reason the function returns a std::ostream is so that you can chain calls to the function. If you look carefully,
std::cout << 0 << 1;
is in fact a chain of two calls to the insertion operator overload function. Once to output 0, and then to output 1. It is equivalent to
std::operator<<(std::operator<<(std::cout, 0), 1);
The first call to insert 0 returns an output stream, and the second call to insert 1 takes that returned output stream and inserts into that 1. That's why we return the output stream: so we can chain calls.
You will also note that the insertion operator has a left-to-right associativity, which means that in the above statement 0 is guaranteed to be output first, and 1 second. This as opposed to the equivalent line I wrote above, in which the associativity (of function calls) is inside-out. This yields a much less readable code IMO, and that's one of the benefits of using operator << for output semantics.
Next look at the function's parameters. The first parameter, a std::ostream, is taken by reference. This so you can change the stream. That's also why the stream is not taken by const reference.
The second parameter can be taken by const reference, because we don't want to change it, just read it. However, we do want to take it by reference, again because we don't intend to change it, not even for a local purpose, and so saving the construction of a copy can only be a good idea. It also allows for accepting derivatives of Telegram and caling virtual functions upon them, should the need arise. Also, taking a const reference allows you to output a temporary, as in std::cout << Telegram() << '\n';.
{
os << "time: " << t.DispatchTime << " Sender: " << t.Sender
<< " Receiver: " << t.Receiver << " Msg: " << t.Msg;
This code should be self explanatory now. Presumably each of the members you insert into the output stream has the insertion operator defined for. The standard library defines insertion into output streams for primitives, for strings, for complex numbers and other standard types.
return os;
}
And finally you return the stream object, so the caller can chain the output with outputting another object. Note that you could simply return the result of the chain:
return os << "time: " << t.DispatchTime << " Sender: " << t.Sender
<< " Receiver: " << t.Receiver << " Msg: " << t.Msg;
Finally, to demonstrate the bonus you get from the use of a free function and taking the Telegram parameter by reference, consider:
struct Telegram {
Telegram();
Telegram(const Communication& c);
virtual ~Telegram();
};
struct Message : public Telegram {
};
struct Letter {
operator Telegram() const;
};
// ...
Telegram t;
Communication c;
Message m;
Letter l;
std::cout << t << '\n'
<< c << '\n'
<< m << '\n'
<< l << '\n';
All using that single function for outputting a Telegram object.