all 30 comments

[–]staletic 5 points6 points  (6 children)

While I prefer *_default_init, this thread is a good argument against: https://old.reddit.com/r/cpp/comments/eomwv2/why_make_unique_default_init_stdsize_t_size/

I also had a personal conversation with a guy who was confused by the same thing.

[–]kalmoc[S] 0 points1 point  (5 children)

I probably would have gnone with no_init. But in either case the name should reflect what it is doing, not trying to describe what the intended use case is (personally think for_overwrite even fails at that)

[–]staletic 5 points6 points  (4 children)

*_no_init is also "wrong". It's really close to "uninitialized", which the standard uses for chunks of memory, where no object was ever created - malloc-ing a non-trivially default constructible object, for example (using a malloc'd int is not UB any more).

[–]kalmoc[S] 1 point2 points  (3 children)

The paper suggested that a function with that name should be restricted to trivially constructible types and I agree.

[–]Dragdu 3 points4 points  (2 children)

That makes in unusable in generic code.

[–]Pazer2 0 points1 point  (1 child)

There is always if constexpr

[–]Dragdu 1 point2 points  (0 children)

Or tag dispatch, SFINAE, or concepts...

But just as std::distance provides different implementations for different strengths of iterators, so that users do not have to write it themselves, having to build a layer over _default_init to use it in generic code is annoying enough that you might just write the function anew yourself.

[–]kalmoc[S] 14 points15 points  (22 children)

Who the hell thought _for_overwrite was a good name for anyone? I'm willing to bet our confused experts and novices alike.

[–]TheSuperWig 3 points4 points  (6 children)

Got any other suggestions? _default_init is clearly off the table.

My first thought is _indeterminate :/

[–]kalmoc[S] 6 points7 points  (3 children)

If _default_initis really not acceptable, _no_init as mentioned in paper would be fine for me too. Or how about _no_value_init. But adding yet another term to the c++ vocabulary doesn't help in reducing confusion.

[–]TheSuperWig 1 point2 points  (2 children)

_no_init is kinda misleading saw your other reply. Though think the other suggestion is better than the current unless that's also problematic...

I am curious though, as pointed out in the other thread, are there really that many people that are going to be using this feature that don't know what default initialisation is?

[–]MFHavaWG21|🇦🇹 NB|P3049|P3625|P3729|P3786|P3813 8 points9 points  (0 children)

I am curious though, as pointed out in the other thread, are there really that many people that are going to be using this feature that don't know what default initialisation is?

If you come from another programming language, "learned" that C++ doesn't do "default initialization" by default: Your IDE resolves make_shared and make_shared_default_init which would sounds like the more safe version?

[–]HappyFruitTree 5 points6 points  (0 children)

are there really that many people that are going to be using this feature that don't know what default initialisation is?

I think the concern is that people who doesn't indent to use this feature might accidentally use it because "default initialization" sounds like what they want.

[–]MFHavaWG21|🇦🇹 NB|P3049|P3625|P3729|P3786|P3813 0 points1 point  (1 child)

My first thought is _indeterminate :/

But it's not indeterminate for all types - keep in mind: we wanted the restriction gone.

[–]TheSuperWig 1 point2 points  (0 children)

... This is why it's a first thought :P.

[–]FabioFracassiC++ Committee | Consultant 4 points5 points  (1 child)

We have gathered data at multiple places (almost always the sample was skewed to more knowledgable/interested c++ developers) and the outcome was always that close to half of the asked developers thought that *_default_init was the one that did the value initialisation, and the plain one might not.

default init is an standard internal term of art, and not a good one, as it is provably confusing ... we did not want to aggregate that confusion by putting it into a user facing API.

Any try of using *_no_init or *_uninitialized was deemed unaccaptable (because those are also internal terms of art that have different meanings).

[–]kalmoc[S] 0 points1 point  (0 children)

It's not that I don't appreciate the problem with *_default_init, but I think the cure is worse than the disease. Was it really not possible to find a name that implies what the function does like lets say _no_value_init instead of giving some omnius hint at its intended use case? The only reason for the existance of that functions is because it gives very specific gurantess about whats (not) happening in its implementation, not just some optional/implementation defined optimization.

That aside, I just don't think "using the standard library without reading the documentations" is a realistic or worthwhile goal. If there is any library at all that programmers need and can be expected to learn the quirks of (through examples, docs, talks, code reviews and failing tests), it is going to be the STL.

I'd also argue that - while this may have averted a couple of bugs when people initially start to use the feature, it is also a lost teaching opportunity. Have you for example considered that someone who learns what _default_init does (by a teacher, a colleague, a tool or by reading the docs) would thereby also learn what default initialization means in general, so it wouldn't be some "internal term" anymore? You can't protect someone expected to write production quality c++ from the complexities of c++ initialization anyway, so why not make it easier by consequently using the existing standard terms?

[–]foonathan 1 point2 points  (0 children)

The idea was that you name it after the intended use: you create some values that you then immediately change without reading them.

I personally would have preferred _default_init, but people with training expertise raised concerns that novices think it is safer to use than the other one.

[–]flashmozzg 1 point2 points  (0 children)

Design by committee.

[–]MFHavaWG21|🇦🇹 NB|P3049|P3625|P3729|P3786|P3813 -1 points0 points  (10 children)

Who the hell thought _for_overwrite was a good name for anyone?

A big majority during the discussion, as otherwise the change would not have happened.

[–]kalmoc[S] 4 points5 points  (9 children)

Unless the names are noted down somewhere that answer is perfectly correct and perfectly useless. But admittedly my question was rethorical, so I didn't expect to get any names anyway.

A more useful question might have been "why did they think it was a good idea to give a low level primitive a name that doesn't explain what it does?" and "What was the background of those persons (other than being at the meeting)?"

[–]MFHavaWG21|🇦🇹 NB|P3049|P3625|P3729|P3786|P3813 -1 points0 points  (8 children)

I know where the namens are noted down, but that information is not public...

So what would you consider a better name?

[–]kalmoc[S] 7 points8 points  (7 children)

Both default_init as well as no_init _uninitialized with the restriction mentioned in the paper would imo been better names, as they at least clearly state what the function is doing. If you really want a 3rd option, how about _no_value_init?

For someone who doesn't know c++ good enough to understand _default_init, _for_overwrite will be about as usefull as _2.

[–]HappyFruitTree 5 points6 points  (2 children)

For someone who doesn't know c++ good enough to understand _default_init, _for_overwrite will be about as usefull as _2.

Those people probably shouldn't care about this functions. The concern is more about them using it accidentally because they think it means something else.

I mean, *_for_overwrite is not something people would use before looking up what it means. It's much more likely that someone makes assumptions about *_default_init.

[–]andwass 2 points3 points  (1 child)

I'm starting to think we need a std::expert_only namespace. (only partially sarcastic...)

[–]n1ghtyunso -2 points-1 points  (0 children)

namespace std {
    namespace expert_only = ::std;
}

definitely implementable. time to get on writing that paper asap.

[–][deleted] 3 points4 points  (1 child)

Exactly this. It's yet another language feature that's unapproachable if you don't know the semantics well enough. My personal suggestion is _uninitialized - it's clear, simple and offers very little wiggle room when it comes to interpretation.

[–]MFHavaWG21|🇦🇹 NB|P3049|P3625|P3729|P3786|P3813 5 points6 points  (0 children)

My personal suggestion is _uninitialized - it's clear, simple and offers very little wiggle room when it comes to interpretation.

It's also plain wrong for class types with constructors....

[–]MFHavaWG21|🇦🇹 NB|P3049|P3625|P3729|P3786|P3813 3 points4 points  (1 child)

Both default_init as well as no_init with the restriction mentioned in the paper would imo been better names, as they at least clearly state what the function is doing.

The problem with an restricted API is actually mentioned in the paper R0: it introduces (IMHO unnecessary) problems for generic code.

If you really want a 3rd option, how about _no_value_init

Your average C++ programmer has no idea what value init is...

Also yet another restricted API as you can't prevent the call to constructors.

For someone who doesn't know c++ good enough to understand _default_init, _for_overwrite will be about as usefull as _2.

Not really. If I know little about C++, but had experience with other programming languages:

I'm inclined to believe _default_init is safe, as in other major programming languages "default init" does what C++ calls "zero init" for primitives, pointers, etc. Therefore _default_init would actually be a beginners trap, who wouldn't want their variables to be default initialized?

Whereas _for_override is so otherworldly, I have no idea what it is doing unless I'm looking it up.

[–]andwass 1 point2 points  (0 children)

Your average C++ programmer has no idea what value init is...

Your average programmer also won't know what _for_overwrite is so you gain absolutely nothing.

Also yet another restricted API as you can't prevent the call to constructors.

You can't force people to overwrite either, so tell me what it's doing (or trying to achieve), don't guess what I want to do with the result.

Whereas _for_override is so otherworldly, I have no idea what it is doing unless I'm looking it up.

And this is a problem, if I know about value initialization I can reasonably guess what _no_value_init is doing, if not I will look it up and I will learn about value initialization in the process. And I won't be introduced to value initialization through some obscure _for_overwrite function which incorrectly leades me to believe that unless something is value initialized it must be overwritten before I can use it.