|Reply-to:||Andrzej Krzemieński <akrzemi1 at gmail dot com>|
This document is a response to National body comment [DE002],
which requests to rename functions
allocate_shared_default_init, as there exist users that incorrectly infer these functions' semantics from
their names. In this paper we list the suggested alternate names for these functions, which have been collected from
the reflector discussions.
The following (potentially contradictory) criteria have been expressed for the desired name of these functions:
This name is consistent with core language and more-less (
make_shared_default_construct) with the Standard Library.
The only problem is the issue inidcated in [DE002], that for
people not familiar with core terms word "init" is misleading as it implies a state that can be read.
Almost same as above, but we get a 100% compatibility with the Standard Library.
make_shared_uninitialized(+ a constraint)
This is what [P1973r0] proposes.
This avoids using the name "initialized" and does not mislead people who infer semantics from function name. To some extent the name reflects what
the function does, because for the types that the function is constrained to, there is little difference between being initialized an uninitialized.
But this solution has its own issues. First, in addition to name, it changes the design,
so that the usage of the function is impeded in generic contexts. The name no longer reflects the core terms or the Standard Library names.
It is also misleading, this time to another group of people, who follow the core terms. "Uninitialized", as in
std::uninitialized_default_construct, implies that we are left with raw memory and some initialization — even if vacuous initialization —
still needs to be performed by the caller.
This is what [P1978r0] proposes. Arguably, its name reflects the intention somewhat better, as the purpose of invoking this function is to perform as fast initialization as possible for the subsequent value assignment. But it departs from core terms, and does not actually address [DE002], because the misleading term "init" is still present.
This is the name used in the original implementation in Boost. It addresses [DE002] as "noinit" implies that no "initialization" is performed. Drawbacks: it doesn't use core terms, and is somewhat misleading as some it might indicate that not even vacuous initialization has been performed.
These names have prefixes that alert about something fishy, but they still have "init", which is potentially misleading. They do not reflect core terms. They also don't really reflect what the function does. Unless we introduce a new core term "weak initialization".
Same as above, except a bit more misleading, as it implies that it only works for trivial types, or that it skips the constructor for types that have one.
"Nonvalue" hints that the produced value may be fishy, but it is not clear if it hints enough that it cannot be read. Still, not following core terms, and has "init".
"Partially formed value" sounds dangerous enough to discourage people form reading the value. It doesn't contain "init". It reflects the intent a bit. But it is not actually true because for types with default constructor the value is actually fully formed.
Clearly reflect the intent. Do not have "init". Do not invent terms. Maybe too descriptive.
Uses familiar core terms, maybe somewhat libelarly. Still, the uninitiated may think that unspecified value can be read.
"Valueless" is used in
std::variant and is perhaps sufficiently scarry.
The two contexts are similar in the sense that in either case you do not want to read the value, but to overwrite it.
You do not want to read a discarded value, don't you?
This uses the core term "indeterminate value" which is the right term at least for trivial types. It is not the right term
for types with default constructor, but the meaning should be sufficiently clear from the context. This makes it incompatible with
The reflector discussions also suggested that the core terms themselves could be changed to be easier to consume by the uninitiated. However, this would require the coordination between the working groups that may not be feasible for C++20. So, either this idea needs to be abandoned, or LEWG can preemptively invent intuitive terms in hopes that CWG will adapt in the future.
It should be noted that
std::make_shared_default_init is acompanied by the
corresponding feature test macro
__cpp_lib_smart_ptr_default_init. Should LEWG decide to change the name of the
function, does the name of the macro also require a change?
make_shared_default_initfunctions and do nothing more", (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1978r0.html).