1

When calling a function in C++, function's name is written followed by () to distinguish it as a function call. Why can't I call stream manipulator functions in the same way?

Why this isn't allowed?:

cout << "Hello!" << endl();

Isn't endl a variable holding \n?

Thanks!

Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
Naveen
  • 623
  • 9
  • 20
  • @KarolyHorvath: So you mean endl is a pointer to a function? :o – Naveen Apr 13 '14 at 13:16
  • I've taken the "Isn't endl a variable holding \n?" out of the question, because it thoroughly confused me (hence my now-deleted comment), and you seem to already recognise `endl` as a function, not a variable. –  Apr 13 '14 at 13:17
  • 1
    yes, the name of a function can be used as a pointer – Karoly Horvath Apr 13 '14 at 13:17
  • @hvd: don't. that's part of his question. he's confused as well - so he needs explanation for it. – Karoly Horvath Apr 13 '14 at 13:18
  • @KarolyHorvath The question as it was (and as you've put it back) just plain doesn't make any sense to me. If `endl` is a function, it isn't a variable. If it were a variable, it wouldn't be a function. –  Apr 13 '14 at 13:25

3 Answers3

3

Stream manipulators are functions. As such, they can be called using the call operator (). Here's how you would call std::endl on a stream:

std::endl(std::cout);

This is the way it would have to be called for each and every stream on which you want to use std::endl. This is because std::endl is a function that takes a returns a reference to a stream object. This is a very quirky way of doing it, so there is a convenience function to stream line the syntax:

std::ostream& operator<<(std::ostream& (*manip)(std::ostream&));

This is an overload of operator<<() that takes a stream on its left hand side and a manipulator on its right hand side. std::endl is technically a function, so it can be converted to a function pointer.

Inside the implementation of this overload, manip is called pretty much how I just showed you. This allows syntax such as:

std::cout << "Hello, World" << std::endl;

If you went ahead and called std::endl using the call operator it will return a reference to the stream. There is another overload of operator<<() that takes a const void* as its argument. That will be the overload that is inadvertently called.

std::cout << std::endl(std::cout); // prints a newline then an address
David G
  • 94,763
  • 41
  • 167
  • 253
2

Manipulators are functions specifically designed to be used in conjunction with the insertion (<<) and extraction (>>) operators on stream objects, for example:

cout << boolalpha;

They are still regular functions and can also be called as any other function using a stream object as argument, for example:

boolalpha (cout);

So, in your code, you can do

cout << "Hello!";
endl(cout);

instead of

cout << "Hello!" << endl;

Source.

HelloWorld123456789
  • 5,299
  • 3
  • 23
  • 33
1

Isn't endl a variable holding \n?

No, it is not. std::endl is a function defined in global namespace

  template<typename _CharT, typename _Traits>
    inline basic_ostream<_CharT, _Traits>& 
    endl(basic_ostream<_CharT, _Traits>& __os)
    { return flush(__os.put(__os.widen('\n'))); }

In expression std::cout << endl_or_something right hand side of << is an argument of a call to operator<< (first argument is std::ostream implicitly). So endl_or_something should be an int, double or other type that can be converted to one of the possible arguments of operator<<. There is an overloaded version of this operator that takes pointers to functions ( functions which take reference to std::ostream and return reference to std::ostream):

  // [27.6.2.5] formatted output
  // [27.6.2.5.3]  basic_ostream::operator<<
  //@{
  /**
   *  @brief  Interface for manipulators.
   *
   *  Manipulators such as @c std::endl and @c std::hex use these
   *  functions in constructs like "std::cout << std::endl".  For more
   *  information, see the iomanip header.
  */
  __ostream_type&
  operator<<(__ostream_type& (*__pf)(__ostream_type&))
  {
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 60. What is a formatted input function?
// The inserters for manipulators are *not* formatted output functions.
return __pf(*this);
  }

Since std::endl signature matches, it can be used in expression

std::cout << "Hello!" << std::endl;

or equivalently

std::cout << "Hello!";
std::endl( std::cout);

Note however that this manipulator is often mistakenly used when a simple newline is desired, leading to poor buffering performance. In such cases use just "\n".


Why this isn't allowed?:

cout << "Hello!" << endl();

std::endl takes one argument, std::ostream. You can see that it can be called with:

return __pf(*this);

means

return std::endl( *this); // std::endl( std::cout);

There is no version of std::endl that takes no parameters so it could be called with

std::endl()

In expression

std::cout << std::endl;

it denotes an argument to operator<<, it is passed as a pointer to function and then called in body of operator<<.

4pie0
  • 29,204
  • 9
  • 82
  • 118
  • Thanks for the clarification! Does it mean the function `operator<<()` takes in an argument called `endl` and `endl` is something defined inside ? – Naveen Apr 13 '14 at 14:12
  • 1
    yes, endl is a function defined in , and operator<< takes its name as a pointer to function – 4pie0 Apr 13 '14 at 14:14