| Document number: | P2042r0 | |
|---|---|---|
| Date: | 2020-01-11 | |
| Audience: | LEWG | |
| Reply-to: | Andrzej Krzemieński <akrzemi1 at gmail dot com> | 
make_shared_default_init This document is a response to National body comment [DE002],
    which requests to rename functions make_shared_default_init, make_unique_default_init and
    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:
make_shared_noinit).
        make_shared_default_init.)
        std::uninitialized_default_construct.)
        make_shared_default_init This name is consistent with core language and more-less (make_shared_default_init vs 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.
    
make_shared_default_constructAlmost 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.
    
make_shared_minimal_initThis 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.
make_shared_noinitThis 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.
make_shared_unsafe_init, make_shared_weak_initThese 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".
make_shared_trivial_initSame 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.
make_shared_nonvalue_init"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".
make_shared_partially_formed_value, make_shared_with_partially_formed_value"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.
make_shared_for_overwrite, make_shared_with_no_guaranteed_valueClearly reflect the intent. Do not have "init". Do not invent terms. Maybe too descriptive.
make_shared_unspecified_valueUses familiar core terms, maybe somewhat libelarly. Still, the uninitiated may think that unspecified value can be read.
make_shared_valueless, make_shared_with_valueless "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.
    
make_shared_with_discarded_value, make_shared_discarded_valueYou do not want to read a discarded value, don't you?
make_shared_indeterminate_value, make_shared_with_indeterminate_value, make_shared_indeterminate 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
    std::uninitialized_default_construct.
    
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_init functions and do nothing more",
	  (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1978r0.html).