问题
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')
回答1:
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`
回答2:
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
andnounitbuf
.Adjustment field manipulators:
internal
,left
andright
.Numeral system base manipulators:
dec
,hex
andoct
.Floating point number presentation manipulators:
fixed
,scientific
,hexfloat
anddefaultfloat
.
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
回答3:
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.
来源:https://stackoverflow.com/questions/20850065/c-send-data-in-one-ostream-to-another-ostream