Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"std::format in C++20" by Peter Gottschling

193 views
Skip to first unread message

Lynn McGuire

unread,
Oct 6, 2020, 5:06:40 PM10/6/20
to
"std::format in C++20" by Peter Gottschling
http://www.modernescpp.com/index.php/std-format-in-c-20

"Today, I'm happy to present Peter Gottschling's guest post to the new
formatting library in C++20: std::format. Thanks to std::format, text
formatting becomes in C++20 as easy as in Python."

"Peter is the author of the must-read book "Discovering Modern C++" for
professional C++ developers."

https://www.amazon.com/Discovering-Modern-Scientists-Programmers-Depth/dp/0134383583

Lynn

Cholo Lennon

unread,
Oct 6, 2020, 9:17:30 PM10/6/20
to
A good complement for the Peter's post is this (relatively short) talk
from CppCon 2020:

"C++20 String Formatting Library: An Overview and Use with Custom Types"
by Marc Gregoire
https://youtu.be/IdM0Z2a4fjU

I have to check it, but I am impressed by its speed (at least by what
Marc Gregoire have said)


--
Cholo Lennon
Bs.As.
ARG


daniel...@gmail.com

unread,
Oct 7, 2020, 5:34:24 AM10/7/20
to
On Tuesday, October 6, 2020 at 5:06:40 PM UTC-4, Lynn McGuire wrote:
> "std::format in C++20" by Peter Gottschling
> http://www.modernescpp.com/index.php/std-format-in-c-20
>
> "Today, I'm happy to present Peter Gottschling's guest post to the new
> formatting library in C++20: std::format. Thanks to std::format, text
> formatting becomes in C++20 as easy as in Python."
>
Given that the direction in modern C++ seemed to be to provide non-throwing
alternatives, notably in the filesystem library and the thread support
library, I was surprised that the format library only supports exceptions to
report errors.

Daniel

Bo Persson

unread,
Oct 7, 2020, 7:05:09 AM10/7/20
to
Perhaps it has something to do with how "exceptional" an error is?

For filesystem, a "file not found" status could be quite common and
pretty easy to handle. Like ask the user to try some other name.

In the format library, about the only error is "incorrect format
string". Definitely not an expected error and rather hard to handle if
you get it as a return value.


Bo Persson

daniel...@gmail.com

unread,
Oct 7, 2020, 9:26:11 AM10/7/20
to
On Wednesday, October 7, 2020 at 7:05:09 AM UTC-4, Bo Persson wrote:
> On 2020-10-07 at 11:34, daniel...@gmail.com wrote:
> > Given that the direction in modern C++ seemed to be to provide non-throwing
> > alternatives, notably in the filesystem library and the thread support
> > library, I was surprised that the format library only supports exceptions to
> > report errors.
> >
> Perhaps it has something to do with how "exceptional" an error is?
>
> For filesystem, a "file not found" status could be quite common and
> pretty easy to handle. Like ask the user to try some other name.
>
The filesystem API supports, e.g.,

namespace fs = std::filesystem;

std::error_code ec;
fs::directory_iterator it("foo", ec);
// check ec
fs::directory_iterator end;
while (it != end)
{
it.increment(ec);
// check ec
}

I doubt if the primary motivation here is ease of handling, as
opposed to allowing exceptions to be avoided altogether.

> In the format library, about the only error is "incorrect format
> string". Definitely not an expected error and rather hard to handle if
> you get it as a return value.
>
For those that have to disable exceptions, which includes a significant portion of
the C++ community including many game developers, an std::terminate seems a
heavy price to pay for a format error.

Daniel

Scott Lurndal

unread,
Oct 7, 2020, 11:47:38 AM10/7/20
to
Lynn McGuire <lynnmc...@gmail.com> writes:
>"std::format in C++20" by Peter Gottschling
> http://www.modernescpp.com/index.php/std-format-in-c-20
>

Peter offers two reasons against using printf/snprintf:

1) It can't be used with user types and
2) It's not type-safe.

Neither reason is fully true nor particularly compelling.

Mr Flibble

unread,
Oct 7, 2020, 1:19:06 PM10/7/20
to
On 07/10/2020 12:04, Bo Persson wrote:
> On 2020-10-07 at 11:34, daniel...@gmail.com wrote:
>> On Tuesday, October 6, 2020 at 5:06:40 PM UTC-4, Lynn McGuire wrote:
>>> "std::format in C++20" by Peter Gottschling
>>> http://www.modernescpp.com/index.php/std-format-in-c-20
>>>
>>> "Today, I'm happy to present Peter Gottschling's guest post to the new
>>> formatting library in C++20: std::format. Thanks to std::format, text
>>> formatting becomes in C++20 as easy as in Python."
>>>
>> Given that the direction in modern C++ seemed to be to provide non-throwing
>> alternatives, notably in the filesystem library and the thread support
>> library, I was surprised that the format library only supports exceptions to
>> report errors.
>>
>
> Perhaps it has something to do with how "exceptional" an error is?
>
> For filesystem, a "file not found" status could be quite common and pretty easy to handle. Like ask the user to try some other name.

I would argue having a file not found exception when attempting to open a file is perfectly acceptable: where does it say that all exceptions must be regarded as fatal?

> In the format library, about the only error is "incorrect format string". Definitely not an expected error and rather hard to handle if you get it as a return value.

/Flibble

--
¬

Keith Thompson

unread,
Oct 7, 2020, 2:03:49 PM10/7/20
to
Can you expand on that? It seems to me that both are true and
compelling.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Mr Flibble

unread,
Oct 7, 2020, 2:05:44 PM10/7/20
to
Bullshit.

/Flibble

--
¬

Jorgen Grahn

unread,
Oct 7, 2020, 2:41:38 PM10/7/20
to
On Wed, 2020-10-07, daniel...@gmail.com wrote:
> On Wednesday, October 7, 2020 at 7:05:09 AM UTC-4, Bo Persson wrote:
>> On 2020-10-07 at 11:34, daniel...@gmail.com wrote:
>> > Given that the direction in modern C++ seemed to be to provide non-throwing
>> > alternatives, notably in the filesystem library and the thread support
>> > library, I was surprised that the format library only supports exceptions to
>> > report errors.
>> >
>> Perhaps it has something to do with how "exceptional" an error is?
>>
>> For filesystem, a "file not found" status could be quite common and
>> pretty easy to handle. Like ask the user to try some other name.

How often is an interactive user really present when a file is opened?
Never, in any of my programs.

I think a better argument is if handling of the error is likely to be
handled locally, rather than after a lot of stack unwinding.

> The filesystem API supports, e.g.,
>
> namespace fs = std::filesystem;
>
> std::error_code ec;
> fs::directory_iterator it("foo", ec);
> // check ec
> fs::directory_iterator end;
> while (it != end)
> {
> it.increment(ec);
> // check ec
> }
>
> I doubt if the primary motivation here is ease of handling, as
> opposed to allowing exceptions to be avoided altogether.
>
>> In the format library, about the only error is "incorrect format
>> string". Definitely not an expected error and rather hard to handle if
>> you get it as a return value.
>>

> For those that have to disable exceptions, which includes a
> significant portion of the C++ community including many game
> developers, an std::terminate seems a heavy price to pay for a
> format error.

Didn't that ship sail decades ago? Most of the standard library
cannot be used without exceptions, so why should this part be
different?

(Not that I care about this part of C++20. I won't have chance to use
it anytime soon, I'm happy with the Unix functions for this, and I've
been disappointed by most Boost libraries I've tried (this one is from
Boost, right?).)

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Jorgen Grahn

unread,
Oct 7, 2020, 3:03:54 PM10/7/20
to
On Tue, 2020-10-06, Lynn McGuire wrote:
> "std::format in C++20" by Peter Gottschling
> http://www.modernescpp.com/index.php/std-format-in-c-20
>
> "Today, I'm happy to present Peter Gottschling's guest post to the new
> formatting library in C++20: std::format. Thanks to std::format, text
> formatting becomes in C++20 as easy as in Python."

Stuff like this:

print("Hello, {name}! The answer is {number}. Goodbye, {name}.\n",
arg("name", name),
arg("number", number));

Which is indeed like the currently popular Python string formatting
interface.

Personally, I get more and more disappointed with every new take on
string formatting. I prefer Python's earlier[1], more printf-like
string formatting.

Printf-style has lots of things speaking for it: available in most
languages I care about (from the shell to C), compact and well-known
since the 1970s.

I would have been happy with a variant which let %s work for const
char*, std::string (and string_view) and any T which can be streamed.
At least if g++ had format string analysis like it does for
std::sprintf.

Perhaps Boost.format's printf-like variant does what I want. I was
under the impression that it was vaguely defined and only vaguely
printf-like, but when I check now the documentation says it
implements Unix98 printf.

Disclaimer: I /am/ happy with defining operator<< for my types, and
I do it a lot.

/Jorgen

[1] It's still there, because TMTOWTDI!

Juha Nieminen

unread,
Oct 7, 2020, 3:10:15 PM10/7/20
to
Keith Thompson <Keith.S.T...@gmail.com> wrote:
> sc...@slp53.sl.home (Scott Lurndal) writes:
>> Lynn McGuire <lynnmc...@gmail.com> writes:
>>>"std::format in C++20" by Peter Gottschling
>>> http://www.modernescpp.com/index.php/std-format-in-c-20
>>
>> Peter offers two reasons against using printf/snprintf:
>>
>> 1) It can't be used with user types and
>> 2) It's not type-safe.
>>
>> Neither reason is fully true nor particularly compelling.
>
> Can you expand on that? It seems to me that both are true and
> compelling.

I assume that for the first one he's talking about the workaround of
implementing some kind of "toString()" function for the custom type,
and using "%s" in the format string for it, so you do it like:

std::printf("The value is %s\n", theValue.toString().c_str());

Of course there are multitudes of problems with that, even if we
disregard the efficiency problem of creating and destroying a
dynamically allocated string there. For one, it cannot easily
be used in generic code where you don't know the actual type
of the thing being printed. In other words, compare:

template<typename T>
void foo(const T& value)
{
// This will work with standard types and custom types alike
std::cout << value << "\n";
}

to:

template<typename T>
void foo(const T& value)
{
std::printf("???\n", value);
}

I suppose you could devise a rather complicated system where can write
something like:

template<typename T>
void foo(const T& value)
{
std::printf("%s\n", toString(value));
}

The problem with this is that formatting options will not be passed to
that toString() function, so it will not know if you want eg. to have
a minimum width, a filler character, or output in hexadecimal.

Another problem is that this kind of toString() function doesn't have access
to the file handle / stream, so it can't eg. call fwrite/ostream::write()
on it, if it wanted, or anything else it could want to do with it.

daniel...@gmail.com

unread,
Oct 7, 2020, 3:25:49 PM10/7/20
to
On Wednesday, October 7, 2020 at 2:41:38 PM UTC-4, Jorgen Grahn wrote:
> On Wed, 2020-10-07, daniel...@gmail.com wrote:
> > For those that have to disable exceptions, which includes a
> > significant portion of the C++ community including many game
> > developers, an std::terminate seems a heavy price to pay for a
> > format error.
> Didn't that ship sail decades ago?

I don't think so. If anything, I think the practice of disabling exceptions
has increased over the last decade, judging from reddit discussions,
requests for open source projects to support throws become calls to
std::terminate, and the extent to which projects have moved to
accommodate that.

> Most of the standard library cannot be used without exceptions,

Well, it can, if exceptions are disabled, throws become calls to
std::terminate.

According to Herb Sutter, if C++ allowed not throwing on precondition violations
and also not on out of memory violations, the vast majority of all C++ standard library
functions can be noexcept. He described progress to that end in this article:
https://herbsutter.com/2018/07/

> so why should this part be different?
>
Much of the post C++11 direction of the standard library has been
to provide alternatives to throwing, seen in the filesystem library and
the thread support library, so why should this part be different?

> (this one is from Boost, right?).)
>
No. From https://github.com/fmtlib/fmt.

Daniel

Mr Flibble

unread,
Oct 7, 2020, 4:08:16 PM10/7/20
to
On 07/10/2020 20:25, daniel...@gmail.com wrote:
> On Wednesday, October 7, 2020 at 2:41:38 PM UTC-4, Jorgen Grahn wrote:
>> On Wed, 2020-10-07, daniel...@gmail.com wrote:
>>> For those that have to disable exceptions, which includes a
>>> significant portion of the C++ community including many game
>>> developers, an std::terminate seems a heavy price to pay for a
>>> format error.
>> Didn't that ship sail decades ago?
>
> I don't think so. If anything, I think the practice of disabling exceptions
> has increased over the last decade, judging from reddit discussions,
> requests for open source projects to support throws become calls to
> std::terminate, and the extent to which projects have moved to
> accommodate that.

Bullshit. Exceptions remain the superior error handling mechanism and that will not change anytime soon.

>
>> Most of the standard library cannot be used without exceptions,
>
> Well, it can, if exceptions are disabled, throws become calls to
> std::terminate.
>
> According to Herb Sutter, if C++ allowed not throwing on precondition violations
> and also not on out of memory violations, the vast majority of all C++ standard library
> functions can be noexcept. He described progress to that end in this article:
> https://herbsutter.com/2018/07/
>
>> so why should this part be different?
>>
> Much of the post C++11 direction of the standard library has been
> to provide alternatives to throwing, seen in the filesystem library and
> the thread support library, so why should this part be different?

More bullshit. std::filesystem provides overloads of all functions, one taking an error code that doesn't throw and one that throws:

The overload that does not take a std::error_code& parameter throws filesystem_error on underlying OS API errors, constructed with p as the first path argument and the OS error code as the error code argument. The overload taking a std::error_code& parameter sets it to the OS API error code if an OS API call fails, and executes ec.clear() if no errors occur. Any overload not marked noexcept may throw std::bad_alloc if memory allocation fails.

Enough with the bullshit already. Exceptions are great.

/Flibble

--
¬

daniel...@gmail.com

unread,
Oct 7, 2020, 4:40:59 PM10/7/20
to
On Wednesday, October 7, 2020 at 4:08:16 PM UTC-4, Mr Flibble wrote:
> On 07/10/2020 20:25, daniel...@gmail.com wrote:
> >>
> > Much of the post C++11 direction of the standard library has been
> > to provide alternatives to throwing, seen in the filesystem library and
> > the thread support library, so why should this part be different?

> More bullshit. std::filesystem provides overloads of all functions,
> one taking an error code that doesn't throw and one that throws:
>
Precisely my point :-)
>
> Enough with the bullshit already. Exceptions are great.
>
From some points of view, not others. But more to the point, given two things:

One, the standard committee's attention to "gradually switching precondition
violations from exceptions to contracts" that "promises to eventually remove a
majority of all exceptions thrown by the standard library", as discussed by Herb
Sutter in https://herbsutter.com/2018/07/, and two, the fact that the post C++11
direction appears to be to provide new features with alternative non throwing
API's, given that, it seems strange that we now have a format library that only
throws.

Although I note that there is a proposal to replace some uses of std::format_error
with compile-time format string checks.

Daniel

Scott Lurndal

unread,
Oct 7, 2020, 6:08:28 PM10/7/20
to
Keith Thompson <Keith.S.T...@gmail.com> writes:
>sc...@slp53.sl.home (Scott Lurndal) writes:
>> Lynn McGuire <lynnmc...@gmail.com> writes:
>>>"std::format in C++20" by Peter Gottschling
>>> http://www.modernescpp.com/index.php/std-format-in-c-20
>>
>> Peter offers two reasons against using printf/snprintf:
>>
>> 1) It can't be used with user types and
>> 2) It's not type-safe.
>>
>> Neither reason is fully true nor particularly compelling.
>
>Can you expand on that? It seems to me that both are true and
>compelling.

Juha touched on 1. to_string() or even "cast" operator overrides
in some cases.

for 2, gcc and clang and others support the ability warn
if the printf specifier doesn't match the type of the
associated argument.

Frankly, in over thirty years of production C++ programming, and
extensive use of snprintf therein, neither of those issues
has been compelling enough to switch to the "<<" nonsense.

It may be compelling for someone just learning the language,
perhaps, but for an experienced programmer? it's just a blip.

Keith Thompson

unread,
Oct 7, 2020, 7:52:03 PM10/7/20
to
sc...@slp53.sl.home (Scott Lurndal) writes:
> Keith Thompson <Keith.S.T...@gmail.com> writes:
>>sc...@slp53.sl.home (Scott Lurndal) writes:
>>> Lynn McGuire <lynnmc...@gmail.com> writes:
>>>>"std::format in C++20" by Peter Gottschling
>>>> http://www.modernescpp.com/index.php/std-format-in-c-20
>>>
>>> Peter offers two reasons against using printf/snprintf:
>>>
>>> 1) It can't be used with user types and
>>> 2) It's not type-safe.
>>>
>>> Neither reason is fully true nor particularly compelling.
>>
>>Can you expand on that? It seems to me that both are true and
>>compelling.
>
> Juha touched on 1. to_string() or even "cast" operator overrides
> in some cases.

Yes, but that creates a strong distinction between types for which
printf already has defined formats and types for which it doesn't.
There's no way to tell printf to accept a user-defined type directly.

> for 2, gcc and clang and others support the ability warn
> if the printf specifier doesn't match the type of the
> associated argument.

Yes, but only if the format string is a string literal.

There are workaround for printf's flaws. And yes, sometimes that's
good enough, but they're only workarounds. (And yes, I'm aware of the
problems with "<<".)

> Frankly, in over thirty years of production C++ programming, and
> extensive use of snprintf therein, neither of those issues
> has been compelling enough to switch to the "<<" nonsense.
>
> It may be compelling for someone just learning the language,
> perhaps, but for an experienced programmer? it's just a blip.

Juha Nieminen

unread,
Oct 8, 2020, 2:29:14 AM10/8/20
to
Scott Lurndal <sc...@slp53.sl.home> wrote:
> Juha touched on 1. to_string() or even "cast" operator overrides
> in some cases.

You didn't address any of my objections to that solution.

Bo Persson

unread,
Oct 8, 2020, 3:26:20 AM10/8/20
to
On 2020-10-07 at 19:18, Mr Flibble wrote:
> On 07/10/2020 12:04, Bo Persson wrote:
>> On 2020-10-07 at 11:34, daniel...@gmail.com wrote:
>>> On Tuesday, October 6, 2020 at 5:06:40 PM UTC-4, Lynn McGuire wrote:
>>>> "std::format in C++20" by Peter Gottschling
>>>> http://www.modernescpp.com/index.php/std-format-in-c-20
>>>>
>>>> "Today, I'm happy to present Peter Gottschling's guest post to the new
>>>> formatting library in C++20: std::format. Thanks to std::format, text
>>>> formatting becomes in C++20 as easy as in Python."
>>>>
>>> Given that the direction in modern C++ seemed to be to provide
>>> non-throwing
>>> alternatives, notably in the filesystem library and the thread support
>>> library, I was surprised that the format library only supports
>>> exceptions to
>>> report errors.
>>>
>>
>> Perhaps it has something to do with how "exceptional" an error is?
>>
>> For filesystem, a "file not found" status could be quite common and
>> pretty easy to handle. Like ask the user to try some other name.
>
> I would argue having a file not found exception when attempting to open
> a file is perfectly acceptable: where does it say that all exceptions
> must be regarded as fatal?

The filesystem library has two versions of most functions, one that uses
an error code and one that throws an exception.

The idea is that if a failure condition is probable and easy to handle
locally, you can use the error code version and (perhaps) retry the
operation. That saves you from having a potentially expensive try-catch
clause that triggers too often.

If the error is not expected, or cannot be handled anyway, you can let
the exception propagate and hope that some other part of the program
knows what to do.


Bo Persson


Juha Nieminen

unread,
Oct 8, 2020, 3:34:45 AM10/8/20
to
daniel...@gmail.com <daniel...@gmail.com> wrote:
> I don't think so. If anything, I think the practice of disabling exceptions
> has increased over the last decade, judging from reddit discussions,
> requests for open source projects to support throws become calls to
> std::terminate, and the extent to which projects have moved to
> accommodate that.

I think that error handling of any kind is almost non-existent in 99.9% of
software projects out there (hobby or professional).

Look at pretty much any software project out there with source code
available, be it C or C++, and you'll probably find zero error handling,
for example related to running out of memory, or writing to a file
failing for some reason. (Perhaps the only kind of error handling that
you ever see is checking if opening a file succeeded or not, and even
this only because it's so common to try to open a file that doesn't
exist. I'm sure that if this were a very rare event, most programs
wouldn't even bother doing that, and would happily misbehave if it
ever happened.)

I would bet that if you take almost any software out there that, for
example, reads or writes files, it will not check for every read or
write that it succeeded, or any other operation that it does (such as
fseed() or ftell()). Heck, almost none of them probaby don't even bother
checking if closing the file succeeded.

Of course one of the most likely scenarios for a catastrophic failure that
a program may experience is running out of memory, and also one of the
things that almost no program ever checks. In C this is particularly
problematic because in principle you would need to make that check in
myriads of places.

The advantage of C++ exceptions is that it makes such checks much easier.
You don't need to litter your code with hundreds and hundreds of checks to
see if a memory allocation failed. Instead, you can strategically place
a few catch blocks, and have the program report the problem and end
gracefully if it happens.

But, of course, 99.9% of C++ programmers don't bother doing that, no matter
how easy it is. Just have the program crash for an unknown reason.

Bo Persson

unread,
Oct 8, 2020, 3:52:14 AM10/8/20
to
On 2020-10-07 at 15:25, daniel...@gmail.com wrote:
> On Wednesday, October 7, 2020 at 7:05:09 AM UTC-4, Bo Persson wrote:
>> On 2020-10-07 at 11:34, daniel...@gmail.com wrote:
>>> Given that the direction in modern C++ seemed to be to provide non-throwing
>>> alternatives, notably in the filesystem library and the thread support
>>> library, I was surprised that the format library only supports exceptions to
>>> report errors.
>>>
>> Perhaps it has something to do with how "exceptional" an error is?
>>
>> For filesystem, a "file not found" status could be quite common and
>> pretty easy to handle. Like ask the user to try some other name.
>>
> The filesystem API supports, e.g.,
>
> namespace fs = std::filesystem;
>
> std::error_code ec;
> fs::directory_iterator it("foo", ec);
> // check ec
> fs::directory_iterator end;
> while (it != end)
> {
> it.increment(ec);
> // check ec
> }
>
> I doubt if the primary motivation here is ease of handling, as
> opposed to allowing exceptions to be avoided altogether.

That's not what the standard document says:

"29.11.6 Error reporting [fs.err.report]
Filesystem library functions often provide two overloads, one that
throws an exception to report file system errors, and another that sets
an error_code. [Note: This supports two common use cases:

— Uses where file system errors are truly exceptional and indicate a
serious failure. Throwing an exception is an appropriate response.

— Uses where file system errors are routine and do not necessarily
represent failure. Returning an error code is the most appropriate
response. This allows application specific error handling, including
simply ignoring the error.

—end note]


>
>> In the format library, about the only error is "incorrect format
>> string". Definitely not an expected error and rather hard to handle if
>> you get it as a return value.
>>
> For those that have to disable exceptions, which includes a significant portion of
> the C++ community including many game developers, an std::terminate seems a
> heavy price to pay for a format error.

For the rest of us, having a type mismatch between the format string and
some other std::format argument is one of those "truly exceptional"
conditions. It should never, ever, happen in production code, so the
exception is not going to throw.

Having an exception that never throws is a lot cheaper than actually
verifying the return code at each call of the funtion. Unless, of
course, we just ignore the error.

Having worked for a bank, I can assure you that a format error can be an
extremely serious problem. Imagine printing the wrong number of digits
on a check. :-(


Bo Persson



David Brown

unread,
Oct 8, 2020, 5:07:16 AM10/8/20
to
On 08/10/2020 09:34, Juha Nieminen wrote:
> daniel...@gmail.com <daniel...@gmail.com> wrote:
>> I don't think so. If anything, I think the practice of disabling exceptions
>> has increased over the last decade, judging from reddit discussions,
>> requests for open source projects to support throws become calls to
>> std::terminate, and the extent to which projects have moved to
>> accommodate that.
>
> I think that error handling of any kind is almost non-existent in 99.9% of
> software projects out there (hobby or professional).
>
> Look at pretty much any software project out there with source code
> available, be it C or C++, and you'll probably find zero error handling,
> for example related to running out of memory, or writing to a file
> failing for some reason. (Perhaps the only kind of error handling that
> you ever see is checking if opening a file succeeded or not, and even
> this only because it's so common to try to open a file that doesn't
> exist. I'm sure that if this were a very rare event, most programs
> wouldn't even bother doing that, and would happily misbehave if it
> ever happened.)
>

It is not unreasonable to prioritise realistic situations. Baring
runaway memory leaks (and those are bugs, not planned error handling
situations) or /extremely/ demanding software, programs on PC's don't
run out of memory. It simply doesn't happen. So any code that you
write to detect and handle out of memory errors is wasted effort,
detracts from the readability of the code, and is untestable. And /if/
an allocation fails, your program is going to hit an OS-detectable fault
as it tries to access non-existent memory. A clean OS-controlled crash
is fine in those truly exceptional circumstances for many programs.

For /some/ code it makes sense to track memory allocation failures, but
for most (especially most application-level code), ignoring it is fine.

To a lesser degree, but with the same principle, for a lot of programs
it is acceptable to assume that if you can open a file for writing, then
writes to it will succeed.

Manfred

unread,
Oct 8, 2020, 8:26:04 AM10/8/20
to
On 10/8/2020 9:34 AM, Juha Nieminen wrote:
> daniel...@gmail.com <daniel...@gmail.com> wrote:
>> I don't think so. If anything, I think the practice of disabling exceptions
>> has increased over the last decade, judging from reddit discussions,
>> requests for open source projects to support throws become calls to
>> std::terminate, and the extent to which projects have moved to
>> accommodate that.
>
> I think that error handling of any kind is almost non-existent in 99.9% of
> software projects out there (hobby or professional).

That's not my experience, for professional code including open source.
Obviously toy hobby programs don't matter.

>
> Look at pretty much any software project out there with source code
> available, be it C or C++, and you'll probably find zero error handling,
> for example related to running out of memory, or writing to a file
> failing for some reason. (Perhaps the only kind of error handling that
> you ever see is checking if opening a file succeeded or not, and even
> this only because it's so common to try to open a file that doesn't
> exist. I'm sure that if this were a very rare event, most programs
> wouldn't even bother doing that, and would happily misbehave if it
> ever happened.)
>
> I would bet that if you take almost any software out there that, for
> example, reads or writes files, it will not check for every read or
> write that it succeeded, or any other operation that it does (such as
> fseed() or ftell()). Heck, almost none of them probaby don't even bother
> checking if closing the file succeeded.

Ditto

>
> Of course one of the most likely scenarios for a catastrophic failure that
> a program may experience is running out of memory, and also one of the
> things that almost no program ever checks. In C this is particularly
> problematic because in principle you would need to make that check in
> myriads of places.

Not really. IME good projects tend to centralize OS calls, so you don't
find bare 'malloc' calls spread all over the code. They are rather
confined inside some wrapper or allocation module. There are multiple
reasons for this. One is error handling (could be as simple as log and
exit), another is performance, since these are expensive calls and the
design wants to keep them under control.

>
> The advantage of C++ exceptions is that it makes such checks much easier.
> You don't need to litter your code with hundreds and hundreds of checks to
> see if a memory allocation failed. Instead, you can strategically place
> a few catch blocks, and have the program report the problem and end
> gracefully if it happens.
>
> But, of course, 99.9% of C++ programmers don't bother doing that, no matter
> how easy it is. Just have the program crash for an unknown reason.
>

Again, not my experience.
But I see that this might be an habit for some Java and C# (.NET)
programmers - it's not that uncommon to find applications written in
those languages that more or less frequently prompt the user with some
incomprehensible message and terminate - very disappointing, and rude
(one of the reasons I like C++ better than those).
Apart of considerations on coding discipline, this may be an argument
against exceptions, since in those languages they are de facto the
/only/ error handling facility.

Bonita Montero

unread,
Oct 8, 2020, 8:32:05 AM10/8/20
to
> I think a better argument is if handling of the error is likely
> to be handled locally, rather than after a lot of stack unwinding.

That depends on the type of error. I/O-errors and memor
-errors are the best to be handled in an outer scope.

Öö Tiib

unread,
Oct 8, 2020, 8:41:19 AM10/8/20
to
Like usual. Topic was that new std::print. But no much of it.
It anyway degraded into typical irrelevant comparison what is
worse printf or << plus point that noobs don't deserve anything
better than we had for decades. I think Neanderthals went extinct
because of such stagnated view.

James Kuyper

unread,
Oct 8, 2020, 10:04:05 AM10/8/20
to
On 10/8/20 3:34 AM, Juha Nieminen wrote:
...
> I think that error handling of any kind is almost non-existent in 99.9% of
> software projects out there (hobby or professional).
>
> Look at pretty much any software project out there with source code
> available, be it C or C++, and you'll probably find zero error handling,
> for example related to running out of memory, or writing to a file
> failing for some reason. (Perhaps the only kind of error handling that
> you ever see is checking if opening a file succeeded or not, and even
> this only because it's so common to try to open a file that doesn't
> exist. I'm sure that if this were a very rare event, most programs
> wouldn't even bother doing that, and would happily misbehave if it
> ever happened.)
>
> I would bet that if you take almost any software out there that, for
> example, reads or writes files, it will not check for every read or
> write that it succeeded, or any other operation that it does (such as
> fseed() or ftell()). Heck, almost none of them probaby don't even bother
> checking if closing the file succeeded.

Because most of my code has involved batch processing, it didn't matter
much how quickly it responded to a failure on output. The only thing
that could be done about such an error is send a copy of the input files
to me for testing to determine why it failed, and the resulting delay
could be hours or days, regardless of whether or not the program
continued processing after the error.
Since a stream's error indicator is sticky, it was acceptable to not
bother checking for an output error until just before closing the file.
This doesn't work on input, since failing to check for I/O errors during
input usually results in unexpected behavior if such an error does occur.

> Of course one of the most likely scenarios for a catastrophic failure that
> a program may experience is running out of memory, and also one of the
> things that almost no program ever checks. In C this is particularly
> problematic because in principle you would need to make that check in
> myriads of places.
>
> The advantage of C++ exceptions is that it makes such checks much easier.
> You don't need to litter your code with hundreds and hundreds of checks to
> see if a memory allocation failed. Instead, you can strategically place
> a few catch blocks, and have the program report the problem and end
> gracefully if it happens.
>
> But, of course, 99.9% of C++ programmers don't bother doing that, no matter
> how easy it is. Just have the program crash for an unknown reason.

There's some truth in that - most of the software I've seen that was
designed by other people fits that description to some degree. However,
I would not consider software that had all of those problems to be
"professional".
Software whose design was entirely my own responsibility is careful
about every single issue you describe, including try-catch around
main(). As a result, some people have gotten the impression that the
primary purpose of my code was to produce error messages. I even once
had a subordinate who prepared a test plan for one of my modules that
triggered every single error condition, but which failed to confirm
whether the code handled non-error conditions correctly.

Scott Lurndal

unread,
Oct 8, 2020, 11:28:41 AM10/8/20
to
Juha Nieminen <nos...@thanks.invalid> writes:
>daniel...@gmail.com <daniel...@gmail.com> wrote:
>> I don't think so. If anything, I think the practice of disabling exceptions
>> has increased over the last decade, judging from reddit discussions,
>> requests for open source projects to support throws become calls to
>> std::terminate, and the extent to which projects have moved to
>> accommodate that.
>
>I think that error handling of any kind is almost non-existent in 99.9% of
>software projects out there (hobby or professional).
>
>Look at pretty much any software project out there with source code
>available, be it C or C++, and you'll probably find zero error handling,

That has not been my experience with any professional C++
application (including two operating systems, a hypervisor,
and a large system used to generate X.509 certificates for
millions of websites).

A very typical example:

uint8 *bp = &e_buffer.at(cmd.s.buf_index);
ssize_t diag = ::pwrite(edp->ed_fd, bp, size, offset);
if (diag != static_cast<ssize_t>(size)) {
e_trace->trace(TRACE_ALWAYS,
"Unable to write %zu bytes to %s@0x%lx: %s\n",
(size_t)512, edp->ed_path, offset,
(errno == EBADF)?"Use 'control connect' command to associate disk file with EMMc card" :strerror(errno));
return false;

Melzzzzz

unread,
Oct 8, 2020, 4:01:46 PM10/8/20
to
I think that format is good thing. Petty that it didn't arrive
earlier...


--
current job title: senior software engineer
skills: c++,c,rust,go,nim,haskell...

press any key to continue or any other to quit...
U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec
Svi smo svedoci - oko 3 godine intenzivne propagande je dovoljno da jedan narod poludi -- Zli Zec
Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi
bili naoruzani. -- Mladen Gogala

Jorgen Grahn

unread,
Oct 9, 2020, 2:11:32 AM10/9/20
to
On Thu, 2020-10-08, Juha Nieminen wrote:
> daniel...@gmail.com <daniel...@gmail.com> wrote:
>> I don't think so. If anything, I think the practice of disabling exceptions
>> has increased over the last decade, judging from reddit discussions,
>> requests for open source projects to support throws become calls to
>> std::terminate, and the extent to which projects have moved to
>> accommodate that.
>
> I think that error handling of any kind is almost non-existent in 99.9% of
> software projects out there (hobby or professional).
>
> Look at pretty much any software project out there with source code
> available, be it C or C++, and you'll probably find zero error handling,
> for example related to running out of memory, or writing to a file
> failing for some reason. (Perhaps the only kind of error handling that
> you ever see is checking if opening a file succeeded or not, and even
> this only because it's so common to try to open a file that doesn't
> exist. I'm sure that if this were a very rare event, most programs
> wouldn't even bother doing that, and would happily misbehave if it
> ever happened.)

Also, if programmers were really interested in handling file I/O
errors, there would be well-known test tools which simulated such
errors. (Perhaps there /are/ such tools, and I haven't been
interested enough to look them up.)

Another area where I/O errors are important, and also more likely, is
network I/O. There you can use e.g. the Linux Traffic Control and
firewall for some of the tests.

Jorgen Grahn

unread,
Oct 9, 2020, 2:22:33 AM10/9/20
to
Partly I agree. Comp.lang.c++ hasn't been very interesting for
decades, and discussions tend to gravitate to a few, old, boring
topics over and over again.

Partly I think it /is/ hard to successfully reinvent something that
already exists: it needs to be /a lot/ better to be worth it.

As we see in this thread, not even ostream formatting won completely
over printf. I can imagine sitting in a project in the future which
uses both printf, ostream formatting, Boost.format (in several
flavors) and this one. I don't look forward to that.

Juha Nieminen

unread,
Oct 9, 2020, 2:32:45 AM10/9/20
to
David Brown <david...@hesbynett.no> wrote:
> It is not unreasonable to prioritise realistic situations. Baring
> runaway memory leaks (and those are bugs, not planned error handling
> situations) or /extremely/ demanding software, programs on PC's don't
> run out of memory. It simply doesn't happen. So any code that you
> write to detect and handle out of memory errors is wasted effort,
> detracts from the readability of the code, and is untestable. And /if/
> an allocation fails, your program is going to hit an OS-detectable fault
> as it tries to access non-existent memory. A clean OS-controlled crash
> is fine in those truly exceptional circumstances for many programs.

When eg. a video game crashes, one has to wonder how often that is because
the developers didn't bother with error handling and just allow the
program to go haywire in certain error situations.

Juha Nieminen

unread,
Oct 9, 2020, 2:36:48 AM10/9/20
to
Jorgen Grahn <grahn...@snipabacken.se> wrote:
> Also, if programmers were really interested in handling file I/O
> errors, there would be well-known test tools which simulated such
> errors. (Perhaps there /are/ such tools, and I haven't been
> interested enough to look them up.)

Well, one of the core ideas of TDD is that file streams can be mocked
up and the code tested for (simulated) file I/O errors using those.

> Another area where I/O errors are important, and also more likely, is
> network I/O. There you can use e.g. the Linux Traffic Control and
> firewall for some of the tests.

Network I/O may be another example where proper error handling is more
common, but only because such errors are likewise more common (eg. no
network connection, etc.)

David Brown

unread,
Oct 9, 2020, 4:53:58 AM10/9/20
to
There is always a cost-benefit trade-off involved. Checking for errors,
and handling them, has many costs. Failing to check for errors that
occur also (obviously) has many costs. Did the video game developers
feel that the error would be so rare that it is better to have an
occasional crash, than to make the game slower for everyone else? Did
the managers feel it was better to release the game earlier than to take
the time to write code that handles the situation? Did some "check
everything" PHB insist that the error handling be written, but no one
tested the handling code as the error didn't occur in the lab, and the
handling code had bugs? Did overworked coders skip the error handling
to meet their deadlines? Yes, you can wonder - but there are /lots/ of
possible explanations.

(Of course, by far the most likely cause of a crash is a bug in the code
that no one spotted, rather than the result of any deliberate decision
or lack of error handling.)

Ian Collins

unread,
Oct 9, 2020, 2:44:33 PM10/9/20
to
On 09/10/2020 19:11, Jorgen Grahn wrote:
> On Thu, 2020-10-08, Juha Nieminen wrote:
>> daniel...@gmail.com <daniel...@gmail.com> wrote:
>>> I don't think so. If anything, I think the practice of disabling exceptions
>>> has increased over the last decade, judging from reddit discussions,
>>> requests for open source projects to support throws become calls to
>>> std::terminate, and the extent to which projects have moved to
>>> accommodate that.
>>
>> I think that error handling of any kind is almost non-existent in 99.9% of
>> software projects out there (hobby or professional).
>>
>> Look at pretty much any software project out there with source code
>> available, be it C or C++, and you'll probably find zero error handling,
>> for example related to running out of memory, or writing to a file
>> failing for some reason. (Perhaps the only kind of error handling that
>> you ever see is checking if opening a file succeeded or not, and even
>> this only because it's so common to try to open a file that doesn't
>> exist. I'm sure that if this were a very rare event, most programs
>> wouldn't even bother doing that, and would happily misbehave if it
>> ever happened.)
>
> Also, if programmers were really interested in handling file I/O
> errors, there would be well-known test tools which simulated such
> errors. (Perhaps there /are/ such tools, and I haven't been
> interested enough to look them up.)

We use a C mocking library I wrote to mock I/O calls which can provide
test data and create an possible error condition. Unit tests shouldn't
use real files or devices.

> Another area where I/O errors are important, and also more likely, is
> network I/O. There you can use e.g. the Linux Traffic Control and
> firewall for some of the tests.

Or simply mock the calls.

--
Ian.

Scott Lurndal

unread,
Oct 9, 2020, 3:54:54 PM10/9/20
to
Or actually have clients that generate the traffic for testing. Or use
PCAP files to inject traffic (e.g. into a TUN/TAP interface). Or use
commercial traffic generators (e.g. IXIA, now Keysight).

We use all of that to test software models (and hardware) for 5G. From generating
RFOE packets in the radio head to processing and converting to IP pkts in the MAC,
to routing packets through 100Gb layer 2 switching and packet processing (e.g. IPsec)
pipelines, the entire path is modeled for both normal and exceptional conditions.

Using public domain software as a proxy to determine that nobody does error handling
is unwise at best.

Ian Collins

unread,
Oct 9, 2020, 4:44:16 PM10/9/20
to
Which is great for system testing, I was talking about unit testing
(maybe I should have been clearer) error handling. Mocking is by far
the best way to generate and test the handling of error conditions.

--
Ian.

Öö Tiib

unread,
Oct 10, 2020, 1:35:09 PM10/10/20
to
IMHO both the printf and ostream<< can be discarded as soon there is
something better. Both are made inefficient by localization support
on one hand but on the other hand that localization support
isn't anywhere close to sufficient to help with anything.
Boost.Format addresses some issues with it but looks nerdy and seems
slow. That std::print also seems to address those issues plus have
less nerdy variants but I haven't measured its performance.

What remains missing in C++ is compile-time encoded/decoded textual
input/output that is useful for text-based protocols. Something
that does something useful like supporting escaping and de-escaping
special characters by some compile time fixed table but is not paying
anything run-time for good for nothing dynamic localization garbage.

0 new messages