
Stop Using Std::endl [video] - lefticus
http://articles.emptycrate.com/2016/04/18/stop_using_std_endl.html
======
makecheck
Don’t optimize prematurely, especially since debugging time is a factor here.

If a long-running program crashes, a missing flush can be the difference
between seeing or not seeing an important detail that preceded the crash.
Instead of going straight to the cause, you might be wasting time exploring
something that happened a bit earlier, or you may be forced to rerun the long
program again to see the same issue with better logging.

Then there’s the inconsistency aspect; if you become used to "\n", and see it
“work” all the time for streams that happen to go to the terminal, you will be
confused when “the same” thing does not have the same behavior for a file
stream. Use the abstraction ("endl") until you know you _need_ it to be
different.

~~~
topspin
Working around a broken API is not premature optimization. Stroustrup et al.
point out the same problem with std::endl[1] and advise the same remedy as the
presentation linked here. Conflating EOL with flush() was a mistake the moment
it was first written.

Systems programming languages aren't about easy troubleshooting. C/C++ APIs
should be performant by default because when they are not we end up working
around them, often badly. If I want the stream flushed I'll configure it to
behave as such or I'll call flush explicitly. Any other mindset belongs in
Python, Java or some other higher level language.

[1]
[https://github.com/isocpp/CppCoreGuidelines/issues/357#issue...](https://github.com/isocpp/CppCoreGuidelines/issues/357#issuecomment-153515258)

~~~
makecheck
I’m not defending the implementation (I hate most of std::iostream), just that
"\n" is not exactly equivalent so switching to that may cause surprising
behavior and create problems. Auto-flush has its uses.

If the main purpose of a program is to generate output then it ought to know
what it’s doing anyway and know how to avoid poor performance. For _most_
programs, I’d say that Unix rules of thumb apply: if you are already trying to
be “silent on success”, your program will either print nothing or maybe an
error or two and not have to worry about print performance. If your program
might only print one error and that doesn’t even show up because a flush
didn’t happen before a crash, there is a big problem.

------
dkopi
TLDR: std::endl causes a flush of the buffer to the file for every new line,
vs "\n" or that doesn't. Flushing the buffer for every new line is costly, and
will slow down your file write.

My addition (which might have been in the video, didn't watch it all): Don't
worry about \r\n vs \n, if you're on windows outputting \n will convert to
\r\n, as long as you opened the file in text mode.

~~~
Arnavion
Personally I use \n for line endings regardless of Windows or not. notepad.exe
can't understand \n and displays everything on one line, but everything else
can.

~~~
byuu
I've completely given up on Notepad compatibility. I can only assume that the
reason Notepad in 2016 can't handle '\n' is due to pure spite by someone high
up inside Microsoft, Hanlon's Razor be damned.

The sad part is it's not even just Notepad. It's the underlying "EDIT" HWND
class itself. So anyone coding in raw Win32 APIs has to basically capture
paste events from the clipboard to transform text into the "\r\n" state, and
upon reading text out of it, potentially convert it back to "\n".

Probably a five-line patch to that class would eliminate so much extra work
for developers. And we could drop the whole ridiculous "text mode" for working
with files while we were at it.

Plus I'm sure there must have been thousands upon thousands of external
requests to Microsoft to be able to use Notepad with all their non-Notepad
text/configuration files over the years.

It's hard to believe this is anything but very deliberate at this point. Add
to this, the mess Microsoft perpetuates with not supporting UTF-8
(std::wstring, wchar_t, _wfopen, non-standard iostream extensions for Unicode
filenames, etc), and one really begins to have a deep seething hatred for
Microsoft.

~~~
unlinker
That's like asking why does Windows use \ instead of /. It's not hatred, it's
just... the way things work. Changing it would be very costly and would create
compatibility problems for decades presumably, so why do it?

~~~
byuu
\ vs / is an interesting example. fopen() and family from MinGW _can_ use / in
paths on Windows. I use that feature all the time. cmd.exe can't, and I
understand that would break things due to the use of / instead of - for flags
in the Windows world.

Whenever it comes to something programming-related that might improve code
portability between different OSes (C99, LF, UTF-8, etc), there's a mountain
of after-the-fact justifications for why it would break backward compatibility
and other such tripe.

But honestly, what would making "EDIT" accept "\n" alone do to break backward-
compatibility? "\r\n" would still work, of course. Is there a group of people
inserting stray "\n"s alone into text files, and expecting Notepad to silently
ignore them and dump all of that text onto the same line? If so, those people
are absolutely horrible :P

But okay, fine. Require a program .Manifest flag to opt-in, then another
special ES_ACCEPT_LF flag with a caveat that it's Windows 10+.

Even all the people that have jumped through hoops with things like hooking
paste operations to transform "\n" into "\r\n" for "EDIT" ... that would still
work just fine, it would just be unnecessary.

The only cost would be that there's a short time where people are trying to
use these "\n" only text files on older versions of Windows. But we've been
dealing with the fallout of that _anyway_ for the past 21+ years now.

You can't possibly tell me that supporting "\n" alone is an immense burden for
a company with as much money and developers as Microsoft. No, I'm sorry, but
this, C99, UTF-8, things like _wfopen, WSAPoll over poll, etc are all very
much intentional: they're designed to maximize vendor lock in. Microsoft
doesn't want your code easily moving between Windows and Linux. Even though
they're a convicted monopoly with a mountain of evidence of their abusive
actions, they still have so many white knights ready to defend their actions
as benign =(

~~~
simoncion
IIRC, '/' as a path component separator works just fine in every Windows API
call that matters that takes a path and (unless I'm remembering wrong) has for
a _really_ long time. It works just fine in Windows 10's version of Windows
Explorer. I would be surprised if it didn't work in W7's Explorer, too.

CMD.EXE is -sadly- a bucket of suck.

> ...WSAPoll over poll...

Don't fucking get me started about the WinSock API. >:(

------
oppositelock
You can use C-library functions in C++, so just use fprintf, and you can flush
however you see fit. I've been writing C++ since basically forever, and find
the streaming operators in C++ to be way too much of a pain. It's doubly
painful if you ever consider internationalizing your software.

fprintf(fd, "Number: %.3f\n", number)

Is a whole lot easier than

std::streamsize ss = std::cout.precision(); std::cout << "Number: " <<
std::setprecision(3) << number << std::setprecision(ss) << std::endl;

Since setting precision is modal, you have to set it back if you don't want to
screw up future output.

Streams suck!

~~~
GFK_of_xmaspast
One thing that streams have that the c routines don't is type safety and
overloading for user-defined output.

Also take a look at cppformat for some of the best of both worlds.

~~~
oppositelock
Yup, cppformat is nice. I could also have a nice type-safe wrapper around libc
functions. It doesn't change the fact that the API in the language is tedious.

When you're doing internationalization, a common thing you might do is
something along these lines:

fprintf(fd, translate_string(context, "Result %d of %d"), num1, num2);

The translation may be "%d of %d results" in another language. It's really
difficult to map that into streams.

Yes, I'm over-simplifying, since you can't have arbitrary placeholders due to
order differences between languages, but it's _much_ harder to write simple
code with streams than libc, and I stand by that!

As for user-defined data, I've added .toString() functions on objects which I
can call whenever needed, either from the ostream operator or pass the result
to libc.

------
pveierland
Also interesting to note is that as opposed to std::cout; std::cerr
(associated with stderr) is automatically flushed, and that std::clog (also
associated with stderr) is not automatically flushed.

[http://en.cppreference.com/w/cpp/io/clog](http://en.cppreference.com/w/cpp/io/clog)

~~~
bostonpete
I guess it's fitting that something called "clog" does not automatically
flush. :-)

------
dkopi
One case where you would want to use endl and not \n is if you're outputting
to something like a log file that's being monitored with tail -f.

------
Joky
This is part of the coding standard for LLVM for years:
[http://llvm.org/docs/CodingStandards.html#avoid-std-
endl](http://llvm.org/docs/CodingStandards.html#avoid-std-endl)

Of course if you're debugging you want to flush ASAP.

------
sickbeard
no. you put that thing in the language. fix the language. This kind of
nonsense is why people don't like using c++, I remember Qt had a similar thing
with QThread. They published a popular article called QThread you're doing it
wrong, and it turns out their own documentation was doing it wrong.

~~~
hellofunk
endl is not broken, and does not need fixing. it's one of several ways to do
things and this video is pointing out that its _documented_ features may not
be exactly what you want, and alternatives are available.

However, sometimes endl is indeed what you want. There is nothing to "fix"
here, except maybe your attitude.

~~~
stormbrew
I think there's a valid argument to be made that it is at least poorly named,
and that naming has resulted in people using it wrong, including among people
who teach the language and so compound the problem.

~~~
arcticbull
Agreed, names are the first line of documentation. Having endl flush is like
using single letter variable names, but maybe a bit worse since single letter
variables make you go find where they were declared but this lulls you into a
false sense of security.

This violated the principal of least surprise enough that someone made a 10
minute long video on it :) It's really hard to blame the user this time.

~~~
smitherfield
People not using descriptive names for the important stuff is probably my
number one pet peeve. We're not on a VAX, bytes aren't precious, and we aren't
naming terminal commands, keystrokes aren't either. And nowadays every editor
has autocomplete, so there's really no excuse.

~~~
arcticbull
The great vowel shortage of the late 80s is finally behind us :)

------
payne92
Or, stop using C++

~~~
chris_wot
Yeah, I'll just go convert the LibreOffice codebase to Go right away.

~~~
sgift
Finished already? I have a JVM that waits to be converted, so I can be sure
that no C++ pollutes my Java code. Kidding aside, I'm still curious if Rust/Go
(or whatever) will be serious contenders to develop current c++ codebases
further, e.g. the old code stays c++ but new code will be written in something
else.

~~~
smitherfield
Rust is probably more appropriate for that, since (like C++) it uses system
APIs directly instead of importing a runtime.

