How does std::endl not use any brackets if it is a function?
Asked Answered
S

3

26

The question is pretty much in the title. According to C++ Reference, std::endl is actually a function. Looking at its declaration in <iostream>, this can be verified.

However, when you use std::endl, you don't use std::endl(). Instead, you use:

std::cout << "Foo" << std::endl;

In fact, if you use std::endl(), the compiler demands more parameters, as noted on the link above.

Would someone care to explain this? What is so special about std::endl? Can we implement functions that do not require any brackets when calling too?

Strutting answered 2/10, 2011 at 0:9 Comment(2)
Although not a duplicate question, the answers here answer your question: 4842901.Spindly
Thanks a lot for that link. It really fully explains it. :)Strutting
S
35

std::endl is a function template declared (27.7.3.8):

template <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);

The reason that you can "stream" it to std::cout is that the basic_ostream class template has a member declared:

basic_ostream<charT,traits>& operator<<
    ( basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&) );

which is defined to have the effect of returning pf(*this) (27.7.3.6.3).

std::endl without parentheses refers to a set of overload functions - all possible specializations of the function template, but used in a context where a function pointer of one particular type is acceptable (i.e. as an argument to operator<<), the correct specialization can be unambiguously deduced.

Spindly answered 2/10, 2011 at 0:19 Comment(2)
Thanks for this explanation! Is there a way of passing std::endl to a class, like in the following: https://mcmap.net/q/16863/-std-endl-is-of-unknown-type-when-overloading-operator-lt-lt/484230Controvert
For those wondering, yes, you can do std::ostream & some_func(std::ostream &stream) { return stream << ":D"; } and use it by doing std::cout << some_func;.Intransigent
S
1

std::endl is an object of some type (not really important) that is supplied as an argument to operator<<( std::ostream &, decltype(std::endl)).

EDIT

Reading the other question would lead me to think that endl is a function template and that we most likely select the ostream& operator<<(ostream&(*)(ostream&)) member function overload.

Splenic answered 2/10, 2011 at 0:12 Comment(5)
std::endl isn't an object (in the C++ sense), it's a function template.Spindly
... which is why there's no std::wendl. I'm not sure if that's a good thing in hindsight.Dobson
@MSalters: I'm not sure how that's a reason.Overhappy
@Tomalak : Well, there's '\n' and a distinct L'\n'. If you're thinking of endl as some object that's like '\n', you'd expect a wendl.Dobson
@MSalters: I agree! Which is why I don't see how that endl is able to be both is a reason that it does.Overhappy
O
1

Though it's a function [template], standard stream manipulators are designed to be sent to streams as function pointers (or functor object references). Inserting the result of a function call won't give you anything but the value that results from that function call.

This means that you stream the functor itself (f), rather than the result of calling it (f()).

Overhappy answered 2/10, 2011 at 0:28 Comment(2)
Note: My phone really needs a backtick key.Overhappy
std::endl isn't a class with an operator(); it's a function template.Spindly

© 2022 - 2024 — McMap. All rights reserved.