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

"Functional exception-less error handling with C++23’s optional and expected" by Sy Brand

349 views
Skip to first unread message

Lynn McGuire

unread,
Apr 19, 2023, 5:13:54 PM4/19/23
to
"Functional exception-less error handling with C++23’s optional and
expected" by Sy Brand
https://devblogs.microsoft.com/cppblog/cpp23s-optional-and-expected/

"In software things can go wrong. Sometimes we might expect them to go
wrong. Sometimes it’s a surprise. In most cases we want to build in some
way of handling these misfortunes. Let’s call them disappointments."

"std::optional was added in C++17 to provide a new standard way of
expressing disappointments and more, and it has been extended in C++23
with a new interface inspired by functional programming."

Lynn

Mut...@dastardlyhq.com

unread,
Apr 20, 2023, 4:27:24 AM4/20/23
to
Sorry, std::optional is totally pointless. All it does is save manually
creating a pair/tuple at the point of return. Any function that requires
returning a large amount of data will almost certainly do it via a parameter
reference anyway and simply return a boolean value as success/failure so
std::optionals entire use case is functions that return simple values where
a success/failure boolean is required too.

Paavo Helde

unread,
Apr 20, 2023, 4:56:49 AM4/20/23
to
20.04.2023 11:27 Mut...@dastardlyhq.com kirjutas:

> Any function that requires
> returning a large amount of data will almost certainly do it via a parameter
> reference anyway
Why would that be? Returning data as (a part of) the function return
value is cleaner and potentially faster. Non-const reference parameters
just complicate things, both for human readers and for the optimizer.

Mut...@dastardlyhq.com

unread,
Apr 20, 2023, 5:37:08 AM4/20/23
to
On Thu, 20 Apr 2023 11:56:32 +0300
Paavo Helde <ees...@osa.pri.ee> wrote:
>20.04.2023 11:27 Mut...@dastardlyhq.com kirjutas:
>
>> Any function that requires
>> returning a large amount of data will almost certainly do it via a parameter
>> reference anyway
>Why would that be? Returning data as (a part of) the function return
>value is cleaner and potentially faster. Non-const reference parameters

So copying an array with 1 billion entries into a function then copying it
out again is more efficient than simply updating the reference is it?

>just complicate things, both for human readers and for the optimizer.

Umm, no.

Bonita Montero

unread,
Apr 20, 2023, 6:34:57 AM4/20/23
to
Am 19.04.2023 um 23:13 schrieb Lynn McGuire:

> "Functional exception-less error handling with C++23’s optional and
> expected" by Sy Brand
>    https://devblogs.microsoft.com/cppblog/cpp23s-optional-and-expected/

Nice, this "expected" variant class. I think that's taken from Rust
which also returns result/error-"pairs". If you want to communicate
your error directly to the caller that's more convenient than excep-
tions. But for hard errors which go throuh multiple call-levels (e.e.
bad_alloc or system_error) exceptions are faster when nothing happens.
I think many developers returned their own error-variant so far so
it's good that this gets it own standard to make code more readabel.

Bonita Montero

unread,
Apr 20, 2023, 6:39:14 AM4/20/23
to
I just checked the size of expected<int, int> and it's 8, so expected
actually isn't a variant, what makes access more efficient.

Paavo Helde

unread,
Apr 20, 2023, 7:20:28 AM4/20/23
to
20.04.2023 12:36 Mut...@dastardlyhq.com kirjutas:
> On Thu, 20 Apr 2023 11:56:32 +0300
> Paavo Helde <ees...@osa.pri.ee> wrote:
>> 20.04.2023 11:27 Mut...@dastardlyhq.com kirjutas:
>>
>>> Any function that requires
>>> returning a large amount of data will almost certainly do it via a parameter
>>> reference anyway
>> Why would that be? Returning data as (a part of) the function return
>> value is cleaner and potentially faster. Non-const reference parameters
>
> So copying an array with 1 billion entries into a function then copying it
> out again is more efficient than simply updating the reference is it?

Ever heard about RVO and move semantics? Welcome to the modern ages!


Bonita Montero

unread,
Apr 20, 2023, 9:16:33 AM4/20/23
to
No, it's a union with VC++:

union {
_Ty _Value;
_Err _Unexpected;
};
bool _Has_value;

David Brown

unread,
Apr 20, 2023, 11:00:17 AM4/20/23
to
Perhaps you got that idea from working with old C compilers and old C
code, where programmers were allergic to creating structs and would
rather use an ugly and error-prone mix of pointer parameters instead of
returning the function's results in the natural way - as the return value.

When a function (C or C++) returns a struct that is too big to fit in
registers, it is implemented by the calling function passing a hidden
pointer parameter for the return value - there's no need to do it
manually. C++ RVO guarantees you avoid extra coping in many cases.

If the data is big enough that you don't want it in your local frame,
you'll likely be using some kind of ownership class to handle the
resource and heap management in a clean RAII manner.

std::optional<> is extremely convenient. It is mostly just a wrapper
for making a struct of a boolean and the contained type, but it is a
very handy wrapper for that purpose. Many programming languages have
some kind of "Optional" or "Maybe" type, because they are very useful in
practice.

Bonita Montero

unread,
Apr 20, 2023, 11:24:36 AM4/20/23
to
Am 20.04.2023 um 10:27 schrieb Mut...@dastardlyhq.com:

> Sorry, std::optional is totally pointless. ...
It seems that everything that overwhelms you is pointless technology.
My code regularly sounds like Swahili to you.
If you have a native type you can reserve a value for "not a valid
value", such as with floating point values where there is a NaN.
But that's no longer possible with more complex objects. There
an optional<> is optimal, because it knows an invalid state. The
nice thing about it is that the optional object does not even have
to be instantiated or destroyed later, which may save runtime.
An optional<> can also contain heavyweight objects that only have
to be created if it is really necessary. This is a common code
pattern that, thanks to optional<>, does not have to be reworked
manually every time.

Ben Bacarisse

unread,
Apr 20, 2023, 11:39:42 AM4/20/23
to
Mut...@dastardlyhq.com writes:

> On Thu, 20 Apr 2023 11:56:32 +0300
> Paavo Helde <ees...@osa.pri.ee> wrote:
>>20.04.2023 11:27 Mut...@dastardlyhq.com kirjutas:
>>
>>> Any function that requires
>>> returning a large amount of data will almost certainly do it via a parameter
>>> reference anyway
>>Why would that be? Returning data as (a part of) the function return
>>value is cleaner and potentially faster. Non-const reference parameters
>
> So copying an array with 1 billion entries into a function then copying it
> out again is more efficient than simply updating the reference is it?

Bait and switch. A function that should modify an array needs to do so
via a reference (or pointer). This has nothing to do with what
std::optional is for, nor with the "trick" of passing in a reference to
receive a large value that might otherwise be returned by the function.

A typical use might be a function that computed the inverse of a matrix.
There may be no inverse, so std::optional is a reasonable type to
return. In the past, the value might well have been "returned" via
reference parameter.

--
Ben.

Mut...@dastardlyhq.com

unread,
Apr 20, 2023, 11:55:35 AM4/20/23
to
On Thu, 20 Apr 2023 14:20:12 +0300
Paavo Helde <ees...@osa.pri.ee> wrote:
>20.04.2023 12:36 Mut...@dastardlyhq.com kirjutas:
>> On Thu, 20 Apr 2023 11:56:32 +0300
>> Paavo Helde <ees...@osa.pri.ee> wrote:
>>> 20.04.2023 11:27 Mut...@dastardlyhq.com kirjutas:
>>>
>>>> Any function that requires
>>>> returning a large amount of data will almost certainly do it via a
>parameter
>>>> reference anyway
>>> Why would that be? Returning data as (a part of) the function return
>>> value is cleaner and potentially faster. Non-const reference parameters
>>
>> So copying an array with 1 billion entries into a function then copying it
>> out again is more efficient than simply updating the reference is it?
>
>Ever heard about RVO and move semantics? Welcome to the modern ages!
>

1) Create and update local array, move 1 billion elements on return.

or

2) Update reference array directly.

Which do you think is more efficient?

Welcome to proper programming!

Mut...@dastardlyhq.com

unread,
Apr 20, 2023, 11:58:22 AM4/20/23
to
On Thu, 20 Apr 2023 16:59:59 +0200
David Brown <david...@hesbynett.no> wrote:
>On 20/04/2023 10:27, Mut...@dastardlyhq.com wrote:
>> Sorry, std::optional is totally pointless. All it does is save manually
>> creating a pair/tuple at the point of return. Any function that requires
>> returning a large amount of data will almost certainly do it via a parameter
>> reference anyway and simply return a boolean value as success/failure so
>> std::optionals entire use case is functions that return simple values where
>> a success/failure boolean is required too.
>>
>
>Perhaps you got that idea from working with old C compilers and old C

Nope.

>std::optional<> is extremely convenient. It is mostly just a wrapper

Its an ugly mess. value()/value_or(), exception handling required, seriously?
Thanks, but I'll stick with a simple bool return value.


Mut...@dastardlyhq.com

unread,
Apr 20, 2023, 11:59:11 AM4/20/23
to
On Thu, 20 Apr 2023 17:26:23 +0200
Bonita Montero <Bonita....@gmail.com> wrote:
>Am 20.04.2023 um 10:27 schrieb Mut...@dastardlyhq.com:
>
>> Sorry, std::optional is totally pointless. ...
>It seems that everything that overwhelms you is pointless technology.

Unlike you I write code to do a job, not with an obfuscated fashion show.

Bonita Montero

unread,
Apr 20, 2023, 11:59:58 AM4/20/23
to
This "obfuscation" saves work.


Bonita Montero

unread,
Apr 20, 2023, 12:01:22 PM4/20/23
to
Am 20.04.2023 um 17:58 schrieb Mut...@dastardlyhq.com:

> Its an ugly mess. value()/value_or(), exception handling required, seriously?
> Thanks, but I'll stick with a simple bool return value.

The type of error may be relevant to a user.

Mut...@dastardlyhq.com

unread,
Apr 20, 2023, 12:10:20 PM4/20/23
to
On Thu, 20 Apr 2023 18:01:46 +0200
Bonita Montero <Bonita....@gmail.com> wrote:
>Am 20.04.2023 um 17:58 schrieb Mut...@dastardlyhq.com:
>> On Thu, 20 Apr 2023 17:26:23 +0200
>> Bonita Montero <Bonita....@gmail.com> wrote:
>>> Am 20.04.2023 um 10:27 schrieb Mut...@dastardlyhq.com:
>>>
>>>> Sorry, std::optional is totally pointless. ...
>>> It seems that everything that overwhelms you is pointless technology.
>>
>> Unlike you I write code to do a job, not with an obfuscated fashion show.
>
>This "obfuscation" saves work.

Not when some poor sod has to decode the gibberish to figure out what it
actually does (which in your case is usually very little, all show and no go).


Mut...@dastardlyhq.com

unread,
Apr 20, 2023, 12:11:54 PM4/20/23
to
Then throw a standard exception, don't have some frankenstein combination of
std::optional return value then a potential exception when you try to process
it.

David Brown

unread,
Apr 20, 2023, 12:14:13 PM4/20/23
to
No, I assume you are not being serious.

I use it in my embedded systems, with exceptions disabled, and it is
simple, convenient in the code, and efficient in the implementation.

You only need exceptions if you like to program by crashing ahead
blindly, and trying to clear up the mess when something goes wrong -
such as by using the "value()" method without bothering to check for
validity. That would, of course, defeat the whole point of using optionals.


Typical usage for me is :

extern std::optional<Item> get_next_item();


auto item = get_next_item();
if (item) handle(*item);

or :

if (auto item = get_next_item(); item) handle(item);


Sometimes I will use value_or() :

auto config_port = get_config("port number");
open_port(config_port.value_or(default_port_no));

It is much cleaner and simpler than faffing around with passing pointers
and using bool returns, is often more efficient, and works better with
static error checking (such as checking for initialised variables).

Bonita Montero

unread,
Apr 20, 2023, 12:36:06 PM4/20/23
to
Am 20.04.2023 um 18:11 schrieb Mut...@dastardlyhq.com:
> On Thu, 20 Apr 2023 18:03:11 +0200
> Bonita Montero <Bonita....@gmail.com> wrote:
>> Am 20.04.2023 um 17:58 schrieb Mut...@dastardlyhq.com:
>>
>>> Its an ugly mess. value()/value_or(), exception handling required, seriously?
>>
>>> Thanks, but I'll stick with a simple bool return value.
>>
>> The type of error may be relevant to a user.
>
> Then throw a standard exception, ...

Thrown exceptions are extremely slow (> 10.000 cycles) and
often the return value should be passed directly to the caller.

Bonita Montero

unread,
Apr 20, 2023, 12:36:46 PM4/20/23
to
Am 20.04.2023 um 18:10 schrieb Mut...@dastardlyhq.com:

> Not when some poor sod has to decode the gibberish to figure out what it
> actually does ...
That's not a big deal if you know the language.

Paavo Helde

unread,
Apr 20, 2023, 1:23:03 PM4/20/23
to
Local C array of 1 billion elements would run out of stack space,
regardless of whether it resides in the leaf function or in the calling
function.

Ergo, one would need to use a std::vector instead, which can be returned
efficiently. Thus there is no reason to use a reference parameter.



Mut...@dastardlyhq.com

unread,
Apr 21, 2023, 6:16:31 AM4/21/23
to
On Thu, 20 Apr 2023 18:37:52 +0200
Bonita Montero <Bonita....@gmail.com> wrote:
>Am 20.04.2023 um 18:11 schrieb Mut...@dastardlyhq.com:
>> On Thu, 20 Apr 2023 18:03:11 +0200
>> Bonita Montero <Bonita....@gmail.com> wrote:
>>> Am 20.04.2023 um 17:58 schrieb Mut...@dastardlyhq.com:
>>>
>>>> Its an ugly mess. value()/value_or(), exception handling required,
>seriously?
>>>
>>>> Thanks, but I'll stick with a simple bool return value.
>>>
>>> The type of error may be relevant to a user.
>>
>> Then throw a standard exception, ...
>
>Thrown exceptions are extremely slow (> 10.000 cycles) and
>often the return value should be passed directly to the caller.

Then use an int return value signalling the error. I mean FFS, this isn't
rocket science.

Mut...@dastardlyhq.com

unread,
Apr 21, 2023, 6:17:53 AM4/21/23
to
C++ is too big for one person to know all of it know, particularly the obscure
meta programming side who use cases are limited to say the least.

When I have to debug code I expect to spend time examining the logic of the
code as a whole, not having to decode the syntax of each individual line.

Mut...@dastardlyhq.com

unread,
Apr 21, 2023, 6:19:01 AM4/21/23
to
On Thu, 20 Apr 2023 20:22:46 +0300
Unless the return does nothing then it will be less efficient than updating
the reference object directly.

Bonita Montero

unread,
Apr 21, 2023, 7:29:36 AM4/21/23
to
Am 21.04.2023 um 12:16 schrieb Mut...@dastardlyhq.com:

> Then use an int return value signalling the error.
> I mean FFS, this isn't rocket science.

std::expected<> is an error code _and_ a result. It's a space-saving
variant data structure. I think it happens quite often that people
simply have a pair<> with an result and and error code; std::expetec-
ted is intended to be a standard-mechanism for that so you won't have
to check for specialities in every home-built code. This would save
time to read other's code.


Bonita Montero

unread,
Apr 21, 2023, 7:30:57 AM4/21/23
to
Am 21.04.2023 um 12:17 schrieb Mut...@dastardlyhq.com:

>> That's not a big deal if you know the language.

> C++ is too big for one person to know all of it know, ...

That's while there's a reference.

Mut...@dastardlyhq.com

unread,
Apr 21, 2023, 9:48:29 AM4/21/23
to
I don't expect to have to spend a lot of my time googling obscure C++
semantics when working on code. Similarly when I'm speaking french I don't
expect to have to keep checking google translate because the person I'm
speaking to thinks he's Moliere and uses all the obscure words he can think
of.

Bonita Montero

unread,
Apr 21, 2023, 1:29:41 PM4/21/23
to
Am 21.04.2023 um 15:48 schrieb Mut...@dastardlyhq.com:

> I don't expect to have to spend a lot of my time googling obscure C++
> semantics when working on code. ...

Use a different language if you'd like to program like with C++98.


Mut...@dastardlyhq.com

unread,
Apr 22, 2023, 5:20:00 AM4/22/23
to
When you ever work in a corporate enviroment where code has to be clear and
maintainable by people of varying abilities then maybe you'll get a clue. In
the meantime enjoy life in your academic ivory tower.

Mr Flibble

unread,
Apr 22, 2023, 6:56:11 AM4/22/23
to
std::optional is great and move semantics means returning by value need
not be more expensive than using an out parameter, there is RVO/NRVO
also; additionally, out parameters can be problematic for the optimiser.

/Flibble

Bonita Montero

unread,
Apr 22, 2023, 7:16:01 AM4/22/23
to
Am 22.04.2023 um 11:19 schrieb Mut...@dastardlyhq.com:


> When you ever work in a corporate enviroment where code has to be clear and
> maintainable by people of varying abilities then maybe you'll get a clue. ...

If you're relaxed and reasonably intelligent, you can learn
additional things on the side. My employer currently has two
vacancies that require C++17 and Boost. I think you're saying
the same thing about Boost that you're saying about more modern
C++ features: too complex and unnecessary.
Using modern language usually results in less code and sometimes
just more portable code.

Mut...@dastardlyhq.com

unread,
Apr 22, 2023, 10:42:06 AM4/22/23
to
On Sat, 22 Apr 2023 11:55:54 +0100
Mr Flibble <flib...@reddwarf.jmc.corp> wrote:
>On 22/04/2023 10:19 am, Mut...@dastardlyhq.com wrote:
>> On Fri, 21 Apr 2023 19:31:30 +0200
>> Bonita Montero <Bonita....@gmail.com> wrote:
>>> Am 21.04.2023 um 15:48 schrieb Mut...@dastardlyhq.com:
>>>
>>>> I don't expect to have to spend a lot of my time googling obscure C++
>>>> semantics when working on code. ...
>>>
>>> Use a different language if you'd like to program like with C++98.
>>
>> When you ever work in a corporate enviroment where code has to be clear and
>> maintainable by people of varying abilities then maybe you'll get a clue. In
>> the meantime enjoy life in your academic ivory tower.
>
>std::optional is great and move semantics means returning by value need
>not be more expensive than using an out parameter, there is RVO/NRVO

That depends on what you're doing. If you create a local object/array then
set up its values thats already more expensive that just updating a
reference without the create. Then you have to add the cost of doing the
move upon return. Despite what some people seem to think, move isn't costless.

>also; additionally, out parameters can be problematic for the optimiser.

Optimisers are a black box. The only way you can know which approach is faster
is try both.

Mut...@dastardlyhq.com

unread,
Apr 22, 2023, 10:45:18 AM4/22/23
to
On Sat, 22 Apr 2023 13:17:51 +0200
Bonita Montero <Bonita....@gmail.com> wrote:
>Am 22.04.2023 um 11:19 schrieb Mut...@dastardlyhq.com:
>
>
>> When you ever work in a corporate enviroment where code has to be clear and
>> maintainable by people of varying abilities then maybe you'll get a clue. ...
>
>
>If you're relaxed and reasonably intelligent, you can learn
>additional things on the side. My employer currently has two

Sure you can ,but if you have a deadline you really don't want to have to dig
into some obtuse syntax to figure out what its doing.

>vacancies that require C++17 and Boost. I think you're saying
>the same thing about Boost that you're saying about more modern
>C++ features: too complex and unnecessary.

Its more a case of use where appropriate, not simply because you want to look
like a rockstar coder.

>Using modern language usually results in less code and sometimes
>just more portable code.

As I've already said, a regex can in theory dispense with a huge amount of
code. But sometimes that code would be more intelligable not to mention
flexible.

Mr Flibble

unread,
Apr 22, 2023, 11:20:39 AM4/22/23
to
On 22/04/2023 3:41 pm, Mut...@dastardlyhq.com wrote:
> On Sat, 22 Apr 2023 11:55:54 +0100
> Mr Flibble <flib...@reddwarf.jmc.corp> wrote:
>> On 22/04/2023 10:19 am, Mut...@dastardlyhq.com wrote:
>>> On Fri, 21 Apr 2023 19:31:30 +0200
>>> Bonita Montero <Bonita....@gmail.com> wrote:
>>>> Am 21.04.2023 um 15:48 schrieb Mut...@dastardlyhq.com:
>>>>
>>>>> I don't expect to have to spend a lot of my time googling obscure C++
>>>>> semantics when working on code. ...
>>>>
>>>> Use a different language if you'd like to program like with C++98.
>>>
>>> When you ever work in a corporate enviroment where code has to be clear and
>>> maintainable by people of varying abilities then maybe you'll get a clue. In
>>> the meantime enjoy life in your academic ivory tower.
>>
>> std::optional is great and move semantics means returning by value need
>> not be more expensive than using an out parameter, there is RVO/NRVO
>
> That depends on what you're doing. If you create a local object/array then
> set up its values thats already more expensive that just updating a
> reference without the create. Then you have to add the cost of doing the
> move upon return. Despite what some people seem to think, move isn't costless.

With NRVO you might think you are creating the local object/array in the
stack frame of the current function but with NRVO you are actually
creating it in the caller's stack frame, so zero cost.

>
>> also; additionally, out parameters can be problematic for the optimiser.
>
> Optimisers are a black box. The only way you can know which approach is faster
> is try both.

It is well known that out parameters can be problematic for optimisers.

/Flibble

Bonita Montero

unread,
Apr 22, 2023, 11:25:37 AM4/22/23
to
Am 22.04.2023 um 16:44 schrieb Mut...@dastardlyhq.com:

> Sure you can ,but if you have a deadline you really don't want to
> have to dig into some obtuse syntax to figure out what its doing.

If you have a deadline it's good to learn things which save time.

> Its more a case of use where appropriate, not simply because you
> want to look like a rockstar coder.

Demanding C++17 skills isn't like looking for a rockstar coder.

Bonita Montero

unread,
Apr 22, 2023, 11:45:24 AM4/22/23
to
And you're overburdened with std::expected, which is rather a
variant<> with two variables. You can check it from cpppreference
in 5min. And you're saying that needs a "rockstar developer" ?
I guess you're not developing software at all.

Mut...@dastardlyhq.com

unread,
Apr 22, 2023, 12:15:35 PM4/22/23
to
On Sat, 22 Apr 2023 16:20:24 +0100
Mr Flibble <flib...@reddwarf.jmc.corp> wrote:
>On 22/04/2023 3:41 pm, Mut...@dastardlyhq.com wrote:
>> That depends on what you're doing. If you create a local object/array then
>> set up its values thats already more expensive that just updating a
>> reference without the create. Then you have to add the cost of doing the
>> move upon return. Despite what some people seem to think, move isn't
>costless.
>
>With NRVO you might think you are creating the local object/array in the
>stack frame of the current function but with NRVO you are actually
>creating it in the caller's stack frame, so zero cost.

That depends on whether the compiler does it and if you're writing code for
some system where optimisation is low or switched off for some reason (usually
odd compiler bugs in edge cases) then it won't happen anyway.

Mut...@dastardlyhq.com

unread,
Apr 22, 2023, 12:19:11 PM4/22/23
to
There are many useful things in C++ 17 such as shared_mutex so C++ threads
could finally manage 3 level locking (decades after pthreads), conditional
compilation of constexprs etc, but some of the stuff you post up is just
obfuscation for its own sake.

Mr Flibble

unread,
Apr 22, 2023, 12:23:48 PM4/22/23
to
We should primarily be concerned with the general case, not the obscure
edge case.

/Flibble

Bonita Montero

unread,
Apr 22, 2023, 12:36:51 PM4/22/23
to
Am 22.04.2023 um 18:18 schrieb Mut...@dastardlyhq.com:

> There are many useful things in C++ 17 such as shared_mutex so C++ threads
> could finally manage 3 level locking (decades after pthreads), conditional
> compilation of constexprs etc, but some of the stuff you post up is just
> obfuscation for its own sake.

Everything you're not familiar with is obfuscation.
std::expected<> is that simple and you didn't take 5min to look the doc.

Chris M. Thomasson

unread,
Apr 22, 2023, 4:40:31 PM4/22/23
to
On 4/22/2023 8:27 AM, Bonita Montero wrote:
> Am 22.04.2023 um 16:44 schrieb Mut...@dastardlyhq.com:
>
>> Sure you can ,but if you have a deadline you really don't want to
>> have to dig into some obtuse syntax to figure out what its doing.
>
> If you have a deadline it's good to learn things which save time.

Well, not in the mean time of a deadline. Learn the things first, then
your next deadline just might take less coding time. Fair enough?

Mut...@dastardlyhq.com

unread,
Apr 24, 2023, 4:28:18 AM4/24/23
to
On Sat, 22 Apr 2023 17:23:33 +0100
Obscure edge cases can occur in any sufficiently complex code. If you can't
trust the compilers optimisation then you can't use.

Mut...@dastardlyhq.com

unread,
Apr 24, 2023, 4:31:17 AM4/24/23
to
Given neither the version of clang or gcc I have even support c++20 fully
then I'm not going to bother getting into c++23. But looking at the docs it
seems like yet another useless addition to the language that will almost never
be used and just adds more junk to the standard library. Perfect for someone
like you in other words.

Bonita Montero

unread,
Apr 24, 2023, 4:53:00 AM4/24/23
to
Am 24.04.2023 um 10:30 schrieb Mut...@dastardlyhq.com:

> Given neither the version of clang or gcc I have even support c++20 fully
> then I'm not going to bother getting into c++23. But looking at the docs
> it seems like yet another useless addition to the language that will almost
> never be used and just adds more junk to the standard library. Perfect for
> someone like you in other words.

Everything that overburdens you is useless or obfuscation.


Mut...@dastardlyhq.com

unread,
Apr 24, 2023, 4:57:59 AM4/24/23
to
I've worked in this industry for 25 years so I have a pretty good grasp of
what constructs are useful in a language. This isn't one of them.

Rolling your own version of std::map would probably take even an experienced
C++ dev days to get working. Writing the vaguely useful bits of std::expected
would probably take him 10 mins. So whats the point of putting it in the
library?

Öö Tiib

unread,
Apr 24, 2023, 6:29:13 AM4/24/23
to
Programmers tend to have real features to implement and problems
to solve. You failed to tell why they should waste time to doing beta
testing for gradually emerging half-baked C++23 features instead.

Bonita Montero

unread,
Apr 24, 2023, 7:06:46 AM4/24/23
to
Am 24.04.2023 um 10:57 schrieb Mut...@dastardlyhq.com:

> I've worked in this industry for 25 years so I have a pretty good grasp
> of what constructs are useful in a language. This isn't one of them.

That's not experience, that's an overburdened personality.

Bonita Montero

unread,
Apr 24, 2023, 7:07:28 AM4/24/23
to
Am 24.04.2023 um 12:29 schrieb Öö Tiib:

> Programmers tend to have real features to implement and problems
> to solve. You failed to tell why they should waste time to doing
> beta testing for gradually emerging half-baked C++23 features
> instead.

It's not about beta-testing.
It's about keeping up with what's coming.

Öö Tiib

unread,
Apr 24, 2023, 9:55:06 AM4/24/23
to
I briefly skimmed over that std::expected ... it had no much benefits
compared to std::variant<Success, Failure>.

Not anything even remotely nearing towards convenience of for example
Swift's Or Rust's Result<T, E> .
Look and cry: <https://doc.rust-lang.org/std/result/>
IOW disappointment and can't use anyway unless you want to beta-test
it.

Mut...@dastardlyhq.com

unread,
Apr 24, 2023, 10:51:53 AM4/24/23
to
I don't think overburdened means what you think it means.

Bonita Montero

unread,
Apr 24, 2023, 11:19:21 AM4/24/23
to
Am 24.04.2023 um 15:54 schrieb Öö Tiib:

> I briefly skimmed over that std::expected ... it had no much benefits
> compared to std::variant<Success, Failure>.

The benefit is that if it establishs as a standard way to have
a variant for return- or error-codes code becomes more readable
because people will know this structure. And there's a conversion
to bool to check if the structure has a valid value and a -> ope-
rator to access members of the return-value pat.
That _is_ a usability advantage.


Öö Tiib

unread,
Apr 25, 2023, 3:39:19 AM4/25/23
to
On Monday, 24 April 2023 at 18:19:21 UTC+3, Bonita Montero wrote:
> Am 24.04.2023 um 15:54 schrieb Öö Tiib:
>
> That _is_ a usability advantage.

Disappointingly minor. Not making it worth to beta-test it.

Bonita Montero

unread,
Apr 25, 2023, 8:17:39 AM4/25/23
to
Am 25.04.2023 um 09:39 schrieb Öö Tiib:

> Disappointingly minor. Not making it worth to beta-test it.

Maybe not, but it's necessary to look what's coming up.

Tony Oliver

unread,
Apr 25, 2023, 9:25:04 AM4/25/23
to
On Monday, 24 April 2023 at 14:55:06 UTC+1, Öö Tiib wrote:
> On Monday, 24 April 2023 at 14:07:28 UTC+3, Bonita Montero wrote:
> > Am 24.04.2023 um 12:29 schrieb Öö Tiib:
> >
> > > Programmers tend to have real features to implement and problems
> > > to solve. You failed to tell why they should waste time to doing
> > > beta testing for gradually emerging half-baked C++23 features
> > > instead.
> > It's not about beta-testing.
> > It's about keeping up with what's coming.
>
> I briefly skimmed over that std::expected ... it had no much benefits
> compared to std::variant<Success, Failure>.

Too briefly, it seems. That analogy with std::variant is way off the mark.

> Not anything even remotely nearing towards convenience of for example
> Swift's Or Rust's Result<T, E> .
> Look and cry: <https://doc.rust-lang.org/std/result/>
> IOW disappointment and can't use anyway unless you want to beta-test
> it.

std::expected<T, E> is functionally equivalent to Rust's Result<T, E>.

https://en.cppreference.com/w/cpp/utility/expected#Notes

Öö Tiib

unread,
Apr 25, 2023, 9:58:44 AM4/25/23
to
On Tuesday, 25 April 2023 at 16:25:04 UTC+3, Tony Oliver wrote:
> On Monday, 24 April 2023 at 14:55:06 UTC+1, Öö Tiib wrote:
> > On Monday, 24 April 2023 at 14:07:28 UTC+3, Bonita Montero wrote:
> > > Am 24.04.2023 um 12:29 schrieb Öö Tiib:
> > >
> > > > Programmers tend to have real features to implement and problems
> > > > to solve. You failed to tell why they should waste time to doing
> > > > beta testing for gradually emerging half-baked C++23 features
> > > > instead.
> > > It's not about beta-testing.
> > > It's about keeping up with what's coming.
> >
> > I briefly skimmed over that std::expected ... it had no much benefits
> > compared to std::variant<Success, Failure>.
>
> Too briefly, it seems. That analogy with std::variant is way off the mark.
>
Yes, usage of variant is easier as it has visitors. With that class one got
to write if else chain ... that does not differ much from what Chris mocks
in other thread.

> > Not anything even remotely nearing towards convenience of for example
> > Swift's Or Rust's Result<T, E> .
> > Look and cry: <https://doc.rust-lang.org/std/result/>
> > IOW disappointment and can't use anyway unless you want to beta-test
> > it.
>
> std::expected<T, E> is functionally equivalent to Rust's Result<T, E>.
>
> https://en.cppreference.com/w/cpp/utility/expected#Notes

Claiming functional equivalence with real features we enjoy in other languages
while zero effort was put into convenience of usage (or even usefulness
whatsoever) does describe well the nature of several recent additions to
standard library.
Sad half-baked garbage and good candidates for deprecation.

Bonita Montero

unread,
Apr 25, 2023, 2:28:43 PM4/25/23
to
It's meant to be a standardized way for purposes where you return
a result or an error to the immediate caller. There's nothing wrong
with that, only that new things overburden you.

Chris M. Thomasson

unread,
Apr 25, 2023, 4:32:28 PM4/25/23
to
On 4/25/2023 6:58 AM, Öö Tiib wrote:
> On Tuesday, 25 April 2023 at 16:25:04 UTC+3, Tony Oliver wrote:
>> On Monday, 24 April 2023 at 14:55:06 UTC+1, Öö Tiib wrote:
>>> On Monday, 24 April 2023 at 14:07:28 UTC+3, Bonita Montero wrote:
>>>> Am 24.04.2023 um 12:29 schrieb Öö Tiib:
>>>>
>>>>> Programmers tend to have real features to implement and problems
>>>>> to solve. You failed to tell why they should waste time to doing
>>>>> beta testing for gradually emerging half-baked C++23 features
>>>>> instead.
>>>> It's not about beta-testing.
>>>> It's about keeping up with what's coming.
>>>
>>> I briefly skimmed over that std::expected ... it had no much benefits
>>> compared to std::variant<Success, Failure>.
>>
>> Too briefly, it seems. That analogy with std::variant is way off the mark.
>>
> Yes, usage of variant is easier as it has visitors. With that class one got
> to write if else chain ... that does not differ much from what Chris mocks
> in other thread.

I was not really mocking the "style", just how some programmers do not
like it at all... Personally, I don't mind it. Each function has a
struct for input and a struct for output. So, a function foo would need:
______________________
// function foo input
struct foo_input
{
// whatever...
};


// function foo output
struct foo_output
{
// whatever.
// Usually contains a status for failure or success, ect...
};


// the actual function foo
foo_output
foo(
foo_input const& input
) {
// whatever..

return { // fill in foo_output... };
}
______________________


It works and keeps everything organized, but some people seem to
absolutely hate the style!

Öö Tiib

unread,
Apr 26, 2023, 1:58:12 AM4/26/23
to
On Tuesday, 25 April 2023 at 23:32:28 UTC+3, Chris M. Thomasson wrote:
> On 4/25/2023 6:58 AM, Öö Tiib wrote:
> > On Tuesday, 25 April 2023 at 16:25:04 UTC+3, Tony Oliver wrote:
> >> On Monday, 24 April 2023 at 14:55:06 UTC+1, Öö Tiib wrote:
> >>> On Monday, 24 April 2023 at 14:07:28 UTC+3, Bonita Montero wrote:
> >>>> Am 24.04.2023 um 12:29 schrieb Öö Tiib:
> >>>>
> >>>>> Programmers tend to have real features to implement and problems
> >>>>> to solve. You failed to tell why they should waste time to doing
> >>>>> beta testing for gradually emerging half-baked C++23 features
> >>>>> instead.
> >>>> It's not about beta-testing.
> >>>> It's about keeping up with what's coming.
> >>>
> >>> I briefly skimmed over that std::expected ... it had no much benefits
> >>> compared to std::variant<Success, Failure>.
> >>
> >> Too briefly, it seems. That analogy with std::variant is way off the mark.
> >>
> > Yes, usage of variant is easier as it has visitors. With that class one got
> > to write if else chain ... that does not differ much from what Chris mocks
> > in other thread.
>
> I was not really mocking the "style", just how some programmers do not
> like it at all... Personally, I don't mind it. Each function has a
> struct for input and a struct for output.
>
OK. I do not hate it but I feel it has same issue with returning std::optional
or std::expected, there is additional copy (or hopefully move) made for
composing such function arguments and return value and so it inhibits the
effect (or works in the opposite direction) of NRVO. Especially on
case of heavy-weight "success" objects passed the performance can
drop after refactoring to it. And performance issue means that the
style can not be used idiomatically/uniformly.

David Brown

unread,
Apr 26, 2023, 3:26:53 AM4/26/23
to
In regard to performance issues, you might want to do some testing and
measuring. Small structures on modern processors can be passed and
returned in registers in many cases. The use of structs for parameters
and return values might limit the compiler's choice of registers and
force a bit more register-to-register moves, but these are often almost
free in modern processors since they manipulate the register renaming
maps rather than actually moving data around.

Whether or not you like Chris' style or not is a different matter, of
course - I'm just saying that it will not necessarily have the
performance implications you suggest.

Öö Tiib

unread,
Apr 26, 2023, 6:57:14 AM4/26/23
to
What is the ground of implication that I do not? You think those are my
half-educated guesses? Nope. Those are actually reverted commits because
of proven degradation of performance.

> Small structures on modern processors can be passed and
> returned in registers in many cases. The use of structs for parameters
> and return values might limit the compiler's choice of registers and
> force a bit more register-to-register moves, but these are often almost
> free in modern processors since they manipulate the register renaming
> maps rather than actually moving data around.
>
Note that I mentioned heavy-weight above.

> Whether or not you like Chris' style or not is a different matter, of
> course - I'm just saying that it will not necessarily have the
> performance implications you suggest.
>
It sometimes has and sometimes does not have. I'm repeating for
to point arrive more surely, it cannot be used idiomatically/uniformly.

Mut...@dastardlyhq.com

unread,
May 8, 2023, 11:51:36 AM5/8/23
to
On Thu, 20 Apr 2023 16:59:59 +0200
David Brown <david...@hesbynett.no> wrote:
>Perhaps you got that idea from working with old C compilers and old C
>code, where programmers were allergic to creating structs and would
>rather use an ugly and error-prone mix of pointer parameters instead of
>returning the function's results in the natural way - as the return value.
>
>When a function (C or C++) returns a struct that is too big to fit in
>registers, it is implemented by the calling function passing a hidden
>pointer parameter for the return value - there's no need to do it
>manually. C++ RVO guarantees you avoid extra coping in many cases.

In many cases is not every case so you could end up with performance in the
toilet on certain architectures all because you want to be "pure" and not use
pointers/references.

Also C++ can't change the hardware and if a C++ compiler can optimise returns
so can a C compiler.

>If the data is big enough that you don't want it in your local frame,
>you'll likely be using some kind of ownership class to handle the
>resource and heap management in a clean RAII manner.

ie globals in disguise. Which is fine, but don't pretend its some profoundly
new paradigm.

David Brown

unread,
May 8, 2023, 1:14:50 PM5/8/23
to
On 08/05/2023 17:49, Mut...@dastardlyhq.com wrote:
> On Thu, 20 Apr 2023 16:59:59 +0200
> David Brown <david...@hesbynett.no> wrote:
>> Perhaps you got that idea from working with old C compilers and old C
>> code, where programmers were allergic to creating structs and would
>> rather use an ugly and error-prone mix of pointer parameters instead of
>> returning the function's results in the natural way - as the return value.
>>
>> When a function (C or C++) returns a struct that is too big to fit in
>> registers, it is implemented by the calling function passing a hidden
>> pointer parameter for the return value - there's no need to do it
>> manually. C++ RVO guarantees you avoid extra coping in many cases.
>
> In many cases is not every case so you could end up with performance in the
> toilet on certain architectures all because you want to be "pure" and not use
> pointers/references.

Again - when you have a function (C or C++) that returns a struct that
is too big to fit in registers, it is handled as though the caller had
passed a pointer to a struct to fill up. There will be, at most, minor
differences in the generated code. But if the struct is small enough to
fit in registers (and the ABI supports that), returning a struct will be
more efficient.

I agree that "many cases" is not "every case" - that's why I wrote "many
cases", and not "every case".

>
> Also C++ can't change the hardware and if a C++ compiler can optimise returns
> so can a C compiler.
>

Yes, so you get the same effects with C and C++, as I said. RVO and
copy elision guarantee (C++17) or allow (earlier C++) skipping of
unnecessary copy or move constructors and destructors when returning a
struct or class.

<https://en.cppreference.com/w/cpp/language/copy_elision>

>> If the data is big enough that you don't want it in your local frame,
>> you'll likely be using some kind of ownership class to handle the
>> resource and heap management in a clean RAII manner.
>
> ie globals in disguise. Which is fine, but don't pretend its some profoundly
> new paradigm.
>

No, that is not "globals in disguise". And of course it is not a new
idea - RAII for tracking memory is one of the main reasons for the
existence of C++.


Mr Flibble

unread,
May 8, 2023, 1:27:57 PM5/8/23
to
Globals in disguise? You really are a clueless idiot, nearly as bad as
Bonita.

/Flibble

Malcolm McLean

unread,
May 8, 2023, 1:41:42 PM5/8/23
to
Resources are inherently global. You only have one physical port. Almost
always the system will need some global memory to manage it and
prevent two data sources from connecting to the same port at once.
RAII gives you the illusion that the port is a local object on the stack.
That's not necessarily a bad thing, however.

Mr Flibble

unread,
May 8, 2023, 2:00:25 PM5/8/23
to
Within the context of C++ (i.e., this newsgroup's topic) "globals" have
a distinct and specific meaning: global variables. Resources allocated
using some operating system service with a dynamic rather than fixed
lifetime are nothing like global variables.

/Flibble

Malcolm McLean

unread,
May 8, 2023, 3:04:31 PM5/8/23
to
Of course they are. Think about how you would write malloc() in pure C++
for a small system wth a small, flat memory.

Mr Flibble

unread,
May 8, 2023, 4:29:13 PM5/8/23
to
Yep, thought about it, and my point still stands: you are wrong.

/Flibble

Chris M. Thomasson

unread,
May 8, 2023, 5:18:55 PM5/8/23
to
I have worked on systems that had large input structures. They would be
passed into a function as a const reference. The function would do its
thing, and return a structure that had say a glm::vec3 and a status.
Then I have worked on other systems that had the input and output
structs in the parameters and would return a status in the form of an
unsigned long that had many error conditions packed into said unsigned
value. Kind of like:
____________________
unsigned long
foo(
foo_input const& input,
foo_output& output
) {
// whatever
return 0; // or some status value
}
____________________

Output can be written to, input is constant, and it would return a
status unsigned long to the caller.

Chris M. Thomasson

unread,
May 8, 2023, 5:22:30 PM5/8/23
to
I can write a thread local memory based malloc that still allows for
malloc and free even on different threads. realloc is a little bastard
to impl in this setup, but it can be done.

Mut...@dastardlyhq.com

unread,
May 9, 2023, 4:20:35 AM5/9/23
to
On Mon, 8 May 2023 19:12:35 +0200
David Brown <david...@hesbynett.no> wrote:
>On 08/05/2023 17:49, Mut...@dastardlyhq.com wrote:
>> Also C++ can't change the hardware and if a C++ compiler can optimise returns
>
>> so can a C compiler.
>>
>
>Yes, so you get the same effects with C and C++, as I said. RVO and
>copy elision guarantee (C++17) or allow (earlier C++) skipping of
>unnecessary copy or move constructors and destructors when returning a
>struct or class.

To be fair gcc has been doing that for decades anyway and I assume clang
and VC++ too.

Mut...@dastardlyhq.com

unread,
May 9, 2023, 4:22:50 AM5/9/23
to
If the ownership object/singleton is available to the rest of the program and
not just the function/object in question then its a global. I'm not sure what
the issue is.

Mut...@dastardlyhq.com

unread,
May 9, 2023, 4:25:53 AM5/9/23
to
A realloc equivalent is something that would be a nice to have in the C++
toolbox. Yes you can role your own allocators but it would be great if it was a
built in variant of "new".

Öö Tiib

unread,
May 9, 2023, 6:33:25 AM5/9/23
to
But it was about resource management/managing object in context of RAII
not about singleton. Object like std::unique_ptr, std::vector or std::thread.

It happens that sometimes we can gain lot of performance benefits
in C++ by dumping all that back and forth dynamic monkey-management
of copies and instead keeping data in some common place (like singleton).
However keeping accesses of that common place ordered and transactional
(so one can roll-back half-made changes because of exception) is trick of
its own. That kind of designs weren't under discussion.

David Brown

unread,
May 9, 2023, 9:11:02 AM5/9/23
to
They've been doing a lot of it, yes, but until RVO and copy elision
rules were added to C++, they could not simplify copy-constructor then
destructor sequences if they had observable side effects - or if the
compiler couldn't be sure that they had no observable side effects. As
long as the compiler knows a transformation does not have observable
behaviour, any optimisation is allowed. RVO rules let it do more than
that. And in particular, they allow more efficient return of struct or
class objects even if the compiler cannot see the definitions of the
constructors and destructors at the time.


Bonita Montero

unread,
May 9, 2023, 9:39:15 AM5/9/23
to
Am 09.05.2023 um 10:24 schrieb Mut...@dastardlyhq.com:

> A realloc equivalent is something that would be a nice to have in the C++
> toolbox. Yes you can role your own allocators but it would be great if it
> was a built in variant of "new".

There are containers that do this for free with ::resize( n ).


Mut...@dastardlyhq.com

unread,
May 9, 2023, 11:48:57 AM5/9/23
to
Thats a limited use case. It would be nice if there was a generic way to do it.

Bonita Montero

unread,
May 9, 2023, 11:51:45 AM5/9/23
to
Am 09.05.2023 um 17:48 schrieb Mut...@dastardlyhq.com:

> Thats a limited use case. It would be nice if there was a generic way to do it.

You can do anything with a vector<sth> you can do
with manual memory through malloc() / realloc():

Mut...@dastardlyhq.com

unread,
May 9, 2023, 12:16:47 PM5/9/23
to
You'd still need to write your own allocator (which in turn would need realloc
internally so defeating the point) because the STL doesn't do reallocation, it
does new allocation + copy which is not what realloc is about most of the time.
The point of it is to extend the current allocated memory which is much more
efficient.

Bonita Montero

unread,
May 9, 2023, 12:18:12 PM5/9/23
to
Am 09.05.2023 um 18:14 schrieb Mut...@dastardlyhq.com:

> You'd still need to write your own allocator (which in turn would need realloc
> internally so defeating the point) because the STL doesn't do reallocation, ...

A realloc() is the same as a further malloc(), copy and then free()
of the old block. There's no difference if the container does that
manually.

Mut...@dastardlyhq.com

unread,
May 9, 2023, 12:18:48 PM5/9/23
to
On Tue, 9 May 2023 16:14:29 -0000 (UTC)
Mut...@dastardlyhq.com wrote:
>On Tue, 9 May 2023 17:51:29 +0200
>Bonita Montero <Bonita....@gmail.com> wrote:
>>Am 09.05.2023 um 17:48 schrieb Mut...@dastardlyhq.com:
>>
>>> Thats a limited use case. It would be nice if there was a generic way to do
>>it.
>>
>>You can do anything with a vector<sth> you can do
>>with manual memory through malloc() / realloc():
>
>You'd still need to write your own allocator (which in turn would need realloc
>internally so defeating the point) because the STL doesn't do reallocation, it
>
>does new allocation + copy which is not what realloc is about most of the time.

Ok, allocation + move now but point still stands.

Mut...@dastardlyhq.com

unread,
May 9, 2023, 12:22:50 PM5/9/23
to
No, it absolutely is not the same as that. It first inspects the current memory
block to see if it can be extended. If it can be then it is. Only if it can't
be extended does it do a malloc then copy.

Bonita Montero

unread,
May 9, 2023, 12:22:51 PM5/9/23
to
Am 09.05.2023 um 18:17 schrieb Bonita Montero:

> A realloc() is the same as a further malloc(), copy and then free()
> of the old block. There's no difference if the container does that
> manually.

And a realloc() does a plain memcpy()-like copy. That doesn't fit with
most types inside a vector. And for trivial data types or PODs there's
no performance-advantage if you'd have a realloc with your allocator.

Bonita Montero

unread,
May 9, 2023, 12:57:38 PM5/9/23
to
> No, it absolutely is not the same as that. It first inspects the current memory
> block to see if it can be extended. ...

There's actually no memory allocator that can do in-place reallocation.


Scott Lurndal

unread,
May 9, 2023, 1:03:35 PM5/9/23
to
Mut...@dastardlyhq.com writes:
>On Tue, 9 May 2023 18:17:57 +0200
>Bonita Montero <Bonita....@gmail.com> wrote:
>>Am 09.05.2023 um 18:14 schrieb Mut...@dastardlyhq.com:
>>
>>> You'd still need to write your own allocator (which in turn would need
>>realloc
>>> internally so defeating the point) because the STL doesn't do reallocation,
>>...
>>
>>A realloc() is the same as a further malloc(), copy and then free()
>>of the old block. There's no difference if the container does that
>>manually.
>
>No, it absolutely is not the same as that. It first inspects the current memory
>block to see if it can be extended.

Which is almost _never_ in the real world unless you're using
a buddy allocator, which is wasteful of virtual address space
(and if not paged, memory as well).

Mut...@dastardlyhq.com

unread,
May 9, 2023, 1:12:53 PM5/9/23
to
On Tue, 09 May 2023 17:03:18 GMT
sc...@slp53.sl.home (Scott Lurndal) wrote:
>Mut...@dastardlyhq.com writes:
>>On Tue, 9 May 2023 18:17:57 +0200
>>Bonita Montero <Bonita....@gmail.com> wrote:
>>>Am 09.05.2023 um 18:14 schrieb Mut...@dastardlyhq.com:
>>>
>>>> You'd still need to write your own allocator (which in turn would need
>>>realloc
>>>> internally so defeating the point) because the STL doesn't do reallocation,
>
>>>...
>>>
>>>A realloc() is the same as a further malloc(), copy and then free()
>>>of the old block. There's no difference if the container does that
>>>manually.
>>
>>No, it absolutely is not the same as that. It first inspects the current
>memory
>>block to see if it can be extended.
>
>Which is almost _never_ in the real world unless you're using

You'll have some proof of that then.

Mut...@dastardlyhq.com

unread,
May 9, 2023, 1:12:53 PM5/9/23
to
FFS, do try and keep up. Thats why I said you'd have to write your own.

Mut...@dastardlyhq.com

unread,
May 9, 2023, 1:15:53 PM5/9/23
to
On Tue, 09 May 2023 17:03:18 GMT
sc...@slp53.sl.home (Scott Lurndal) wrote:
fenris$ cat t.c
#include <stdio.h>
#include <stdlib.h>

int main()
{
char *m = (char *)malloc(10000);
printf("%p\n",m);
printf("%p\n",(char *)realloc(m,10100));
return 0;
}
fenris$ cc t.c; a.out
0x7fe976808800
0x7fe976808800
fenris$ uname -a
Darwin fenris 22.3.0 Darwin Kernel Version 22.3.0: Mon Jan 30 20:42:11 PST 2023;
root:xnu-8792.81.3~2/RELEASE_X86_64 x86_64

HTH

Scott Lurndal

unread,
May 9, 2023, 1:38:08 PM5/9/23
to
Now try it after the app has been running for some time
doing thousands of allocations (e.g. for std::string).

Bonita Montero

unread,
May 9, 2023, 1:41:29 PM5/9/23
to
Am 09.05.2023 um 19:10 schrieb Mut...@dastardlyhq.com:

> FFS, do try and keep up. Thats why I said you'd have to write your own.

Have a look at modern allocators like mimalloc, TCMalloc or jemalloc.
With that there's no in-place reallocation.

Mr Flibble

unread,
May 9, 2023, 5:01:16 PM5/9/23
to
The "singleton" provides the resource allocation *service* however the
ownership object is the RAII class which is *not* available to the rest
of the program so it bares no resemblance whatsoever to a global variable.

/Flibble

Mut...@dastardlyhq.com

unread,
May 10, 2023, 4:15:50 AM5/10/23
to
On Tue, 09 May 2023 17:36:00 GMT
So from "never" to after thousands of allocations. Goalpost moving, much?

Obviously if memory becomes fragmented then its less likely to happen but
the fact that it can happen at all means efficiency gains so whats your issue
with it?

Mut...@dastardlyhq.com

unread,
May 10, 2023, 4:16:31 AM5/10/23
to
How is that an advantage?

Malcolm McLean

unread,
May 10, 2023, 5:07:47 AM5/10/23
to
It's not. It's just that the more modern allocator has some advantages over the
standard "free list and control block" allocator. But it doesn't have the advantage that
allocations can sometimes be extended cheaply. People must have found that, for
real programs, this is a price worth paying.

Bonita Montero

unread,
May 10, 2023, 7:48:47 AM5/10/23
to
Am 10.05.2023 um 10:16 schrieb Mut...@dastardlyhq.com:

> How is that an advantage?

It's not a disadvantage.


Mut...@dastardlyhq.com

unread,
May 10, 2023, 10:56:31 AM5/10/23
to
Yes, it is.

Bonita Montero

unread,
May 10, 2023, 11:04:43 AM5/10/23
to
Am 10.05.2023 um 16:56 schrieb Mut...@dastardlyhq.com:

>> It's not a disadvantage.

> Yes, it is.

It's almost never a disadvantage, even more with C++23. With C++23
the allocator has an allocation_result which returns the actual size
of the assigned block, i.e. the allocation can return a larger size
than actually allocated.
With mimalloc, jemalloc and TCMalloc the requested is rounded up to
size has a power of two up to two pages. So there might be a small
advantage if the intial capacity of a vector or basic_string is ac-
tually slightly higher than requested.
With allocations beyond that size the allocation size is rounded up
to the next page size. That might also give a slight advantage but
this becomes smaller as long as the container becomes since the
"blend" is half the size of a page independently of the requested
allocation size.

Mut...@dastardlyhq.com

unread,
May 10, 2023, 12:03:08 PM5/10/23
to
On Wed, 10 May 2023 17:04:25 +0200
Bonita Montero <Bonita....@gmail.com> wrote:
>Am 10.05.2023 um 16:56 schrieb Mut...@dastardlyhq.com:
>
>>> It's not a disadvantage.
>
>> Yes, it is.
>
>It's almost never a disadvantage, even more with C++23. With C++23
>the allocator has an allocation_result which returns the actual size
>of the assigned block, i.e. the allocation can return a larger size
>than actually allocated.
>With mimalloc, jemalloc and TCMalloc the requested is rounded up to
>size has a power of two up to two pages. So there might be a small

So they waste memory. Any idiot can write those sort of allocators. realloc()
is more closely integrated with the OS.

>to the next page size. That might also give a slight advantage but
>this becomes smaller as long as the container becomes since the
>"blend" is half the size of a page independently of the requested
>allocation size.

Sounds like a dumb way to do things unless you're writing an DBMS that will
be allocating huge amounts of memory on the fly. Or java, which just grabs
as much memory as it can on startup up to a specified limit.

Bonita Montero

unread,
May 10, 2023, 12:19:28 PM5/10/23
to
Am 10.05.2023 um 18:00 schrieb Mut...@dastardlyhq.com:

> So they waste memory. ...

A slight amount because the internal fragmentation is not much.

> Sounds like a dumb way to do things unless you're writing an DBMS that will
> be allocating huge amounts of memory on the fly. ...

There's no perfect memory allocator. The three mentioned allocators
currently make the best compromise between blend and performance.

Chris M. Thomasson

unread,
May 10, 2023, 3:26:53 PM5/10/23
to
There is a way to implement realloc in a per-thread allocator but the
problem is that the sizes tend to be rather small to be able to do it
in-place. Its a tradeoff. So making a per-thread allocator generic is
not exactly "easy"...

Usually, at least in my per-thread allocators, we don't need to keep any
meta-data on a per-allocation basis. Instead we over allocate a super
block and aligned it on a large boundary. So, lets say we need to free a
block contained in said super block. We round the address down to the
large boundary. Then we can easily find a header structure to link the
freed block into a LIFO list. This means that the smallest a block can
be is sizeof(void*). There is no meta data that tells one how large a
block is. The requirement that a block be at least the size of a pointer
is to be able to use that space to be able to link it into the LIFO
contained in the header.
It is loading more messages.
0 new messages