1322. Explicit CopyConstructible requirements are insufficient

Section: 16.4.4.2 [utility.arg.requirements] Status: Resolved Submitter: Daniel Krügler Opened: 2010-02-16 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [utility.arg.requirements].

View all issues with Resolved status.

Discussion:

With the acceptance of library defect 822 only direct-initialization is supported, and not copy-initialization in the requirement sets MoveConstructible and CopyConstructible. This is usually a good thing, if only the library implementation needs to obey these restrictions, but the Empire strikes back quickly:

  1. Affects user-code: std::exception_ptr is defined purely via requirements, among them CopyConstructible. A strict reading of the standard would make implementations conforming where std::exception_ptr has an explicit copy-c'tor and user-code must code defensively. This is a very unwanted effect for such an important component like std::exception_ptr.

  2. Wrong re-use: Recently proposed requirement sets (NullablePointer as of N3025, Hash) or cleanup of existing requirement sets (e.g. iterator requirements as of N3046) tend to reuse existing requirement sets, so reusing CopyConstructible is attempting, even in cases, where the intend is to support copy-initialization as well.

  3. Inconsistency: The current iterator requirements set Table 102 (output iterator requirements) and Table 103 (forward iterator requirements) demonstrate quite clearly a strong divergence of copy-semantics: The specified semantics of

    X u(a);
    X u = a;
    

    are underspecified compared to the most recent clarifications of the CopyConstructible requirements, c.f. issue 1309 which is very unsatisfactory. This will become worse for each further issue that involves the CopyConstructible specification (for possible directions see 1173).

The suggested resolution is to define two further requirements implicit-MoveConstructible and implicit-CopyConstructible (or any other reasonable name like MoveConvertible and CopyConvertible) each with a very succinct but precise meaning solving all three problems mentioned above.

[Batavia: Resolved by accepting n3215.]

Proposed resolution:

  1. Add the following new table ?? after Table 34 — MoveConstructible requirements [moveconstructible]:

    Table ?? — Implicit MoveConstructible requirements [implicit.moveconstructible] (in addition to MoveConstructible)
    Expression Operational Semantics
    T u = rv; Equivalent to: T u(rv);
  2. Add the following new table ?? after Table 35 — CopyConstructible requirements [copyconstructible]:

    Table ?? — Implicit CopyConstructible requirements [implicit.copyconstructible] (in addition to CopyConstructible)
    Expression Operational Semantics
    T u = v; Equivalent to: T u(v);
  3. Change 16.4.4.4 [nullablepointer.requirements]/1 as follows:

    A NullablePointer type is a pointer-like type that supports null values. A type P meets the requirements of NullablePointer if:

    • P satisfies the requirements of EqualityComparable, DefaultConstructible, implicit CopyConstructible, CopyAssignable, and Destructible,
    • [..]
  4. Change 16.4.4.5 [hash.requirements]/1 as indicated: [explicit copy-constructible functors could not be provided as arguments to any algorithm that takes these by value. Also a typo is fixed.]

    1 A type H meets the Hash requirements if:

    • it is a function object type (20.8),
    • it satisfiesifes the requirements of implicit CopyConstructible and Destructible (20.2.1),
    • [..]
  5. Change 21.3.2 [meta.rqmts]/1+2 as indicated:

    1 A UnaryTypeTrait describes a property of a type. It shall be a class template that takes one template type argument and, optionally, additional arguments that help define the property being described. It shall be DefaultConstructible, implicit CopyConstructible, [..]

    2 A BinaryTypeTrait describes a relationship between two types. It shall be a class template that takes two template type arguments and, optionally, additional arguments that help define the relationship being described. It shall be DefaultConstructible, implicit CopyConstructible, and [..]

  6. Change 22.10.4 [func.require]/4 as indicated: [explicit copy-constructible functors could not be provided as arguments to any algorithm that takes these by value]

    4 Every call wrapper (20.8.1) shall be implicit MoveConstructible. A simple call wrapper is a call wrapper that is implicit CopyConstructible and CopyAssignable and whose copy constructor, move constructor, and assignment operator do not throw exceptions. [..]

  7. Change 22.10.6 [refwrap]/1 as indicated:

    1 reference_wrapper<T> is an implicit CopyConstructible and CopyAssignable wrapper around a reference to an object or function of type T.

  8. Change 22.10.15.4 [func.bind.bind]/5+9 as indicated:

    5 Remarks: The return type shall satisfy the requirements of implicit MoveConstructible. If all of FD and TiD satisfy the requirements of CopyConstructible, then the return type shall satisfy the requirements of implicit CopyConstructible. [Note: this implies that all of FD and TiD are MoveConstructible. — end note]

    [..]

    9 Remarks: The return type shall satisfy the requirements of implicit MoveConstructible. If all of FD and TiD satisfy the requirements of CopyConstructible, then the return type shall satisfy the requirements of implicit CopyConstructible. [Note: this implies that all of FD and TiD are MoveConstructible. — end note]

  9. Change 22.10.15.5 [func.bind.place] as indicated:

    1 All placeholder types shall be DefaultConstructible and implicit CopyConstructible, and [..]

  10. Change 20.3.1 [unique.ptr]/5 as indicated:

    5 Each object of a type U instantiated form the unique_ptr template specified in this subclause has the strict ownership semantics, specified above, of a unique pointer. In partial satisfaction of these semantics, each such U is implicit MoveConstructible and MoveAssignable, but is not CopyConstructible nor CopyAssignable. The template parameter T of unique_ptr may be an incomplete type.

  11. Change 20.3.2.2 [util.smartptr.shared]/2 as indicated:

    2 Specializations of shared_ptr shall be implicit CopyConstructible, CopyAssignable, and LessThanComparable, [..]

  12. Change 20.3.2.3 [util.smartptr.weak]/2 as indicated:

    2 Specializations of weak_ptr shall be implicit CopyConstructible and CopyAssignable, allowing their use in standard containers. The template parameter T of weak_ptr may be an incomplete type.

  13. Change 24.3.5.2 [iterator.iterators]/2 as indicated: [This fixes a defect in the Iterator requirements. None of the usual algorithms accepting iterators would be usable with iterators with explicit copy-constructors]

    2 A type X satisfies the Iterator requirements if:

    • X satisfies the implicit CopyConstructible, CopyAssignable, and Destructible requirements (20.2.1) and lvalues of type X are swappable (20.2.2), and [..]
    • ...
  14. Change 99 [auto.ptr]/3 as indicated:

    3 [..] Instances of auto_ptr meet the requirements of implicit MoveConstructible and MoveAssignable, but do not meet the requirements of CopyConstructible and CopyAssignable. — end note]