Created on 2025-06-23.00:00:00 last changed 5 days ago
Proposed resolution:
This wording is relative to N5008.
Modify [obj.lifetime] as indicated:
template<class T> constexpr T* relocate(T* first, T* last, T* result);-16- Mandates: […]
-17- Preconditions: […] -18- Effects: […] -19- Returns: `result + (last - first)`. -20- Throws: Nothing. -?- Remarks: If `relocate` is called during constant evaluation, and an exception is thrown by a constructor or destructor of `T`, the call to `relocate` is not a core constant expression ([expr.const]). [Note 3: Overlapping ranges are supported. — end note]
The current specification of `std::relocate` in [obj.lifetime] says
Throws: Nothing.
This is imprecise. A trivially relocatable type may feature a throwing move constructor (or a throwing destructor); for instance, a linked-list implementation with an externally allocated sentinel node may have a throwing move constructor, but still be trivially relocatable. Such a type is nothrow relocatable (as per `is_nothrow_relocatable_v`, cf. [meta.unary.prop]) and therefore one can call `std::relocate` on objects of that type.
During constant evaluation, a call to `std::relocate` is specified to relocate objects via move construction and destruction. (`std::trivially_relocate` is unavailable during constant evaluation.) Since P3068 we are allowed to throw during constant evaluation, and therefore it's unclear whether `std::relocate` should propagate such an exception to the caller or should instead make the evaluation not a constant expression (and therefore make the program ill-formed, since by construction we end up in this possibility during constant evaluation). Given the rationale brought forward for `std::relocate` in P2786 is to be always a nofail operation, I'm proposing a resolution that goes in that direction.History | |||
---|---|---|---|
Date | User | Action | Args |
2025-06-28 13:15:18 | admin | set | messages: + msg14869 |
2025-06-23 00:00:00 | admin | create |