简体   繁体   中英

C++ - Send data in one ostream to another ostream

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')

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 eg 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>&))

  1. Effects: None. Does not behave as a formatted output function (as described in 27.7.3.6.1).

  2. 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

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`

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM