std::optional specialization for reference types

后端 未结 5 2113
时光取名叫无心
时光取名叫无心 2020-12-06 09:34

Why std::optional (std::experimental::optional in libc++ at the moment) does not have specialization for reference types (compared

5条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-06 09:56

    The main problem with std::optional is — what should optRef = obj do in the following case:

    optional optRef;
    …;
    T obj {…};
    optRef = obj; // <-- here!
    

    Variants:

    1. Always rebind — (&optRef)->~optional(); new (&optRef) optional(obj).
    2. Assign through — *optRef = obj (UB when !optRef before).
    3. Bind if empty, assign through otherwise — if (optRef) {do1;} else {do2;}.
    4. No assignment operator — compile-time error "trying to use a deleted operator".

    Pros of every variant:

    1. Always rebind (chosen by boost::optional and n1878):

      • Consistency between the cases when !optRef and optRef.has_value() — post-condition &*optRef == &obj is always met.
      • Consistency with usual optional in the following aspect: for usual optional, if T::operator= is defined to act as destroying and constructing (and some argue that it must be nothing more than optimization for destroying-and-constructing), opt = … de facto acts similarly like (&opt)->~optional(); new (&opt) optional(obj).
    2. Assign through:

      • Consistency with pure T& in the following aspect: for pure T&, ref = … assigns through (not rebinds the ref).
      • Consistency with usual optional in the following aspect: for usual optional, when opt.has_value(), opt = … is required to assign through, not to destroy-and-construct (see template optional& optional::operator=(U&& v) in n3672 and on cppreference.com).
      • Consistency with usual optional in the following aspect: both haveoperator= defined at least somehow.
    3. Bind if empty, assign through otherwise — I see no real benefits, IMHO this variant arises only when proponents of #1 argue with proponents of #2, however formally it's even more consistent with the letter of requirements for template optional& optional::operator=(U&& v) (but not with the spirit, IMHO).

    4. No assignment operator (chosen by n3406):

      • Consistency with pure T& in the following aspect: pure T& doesn't allow to rebind itself.
      • No ambiguous behavior.

    See also:

    • Let’s Talk about std::optional and optional references.
    • Why Optional References Didn’t Make It In C++17.

提交回复
热议问题