This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
Section: 27.11.8 [specialized.construct] Status: New Submitter: Jonathan Wakely Opened: 2020-04-29 Last modified: 2021-12-11
Priority: 2
View other active issues in [specialized.construct].
View all other issues in [specialized.construct].
View all issues with New status.
Discussion:
std::construct_at is ill-formed for array types, because the type of the new-expression is T not T* so it cannot be converted to the return type.
In C++17 allocator_traits::construct did work for arrays, because it returns void so there is no ill-formed conversion. On the other hand, in C++17 allocator_traits::destroy didn't work for arrays, because p->~T() isn't valid. In C++20 allocator_traits::destroy does work, because std::destroy_at treats arrays specially, but allocator_traits::construct no longer works because it uses std::construct_at. It seems unnecessary and/or confusing to remove support for arrays in construct when we're adding it in destroy. I suggest that std::construct_at should also handle arrays. It might be reasonable to restrict that support to the case where sizeof...(Args) == 0, if supporting parenthesized aggregate-initialization is not desirable in std::construct_at.[2020-05-09; Reflector prioritization]
Set priority to 2 after reflector discussions.
[2021-01-16; Zhihao Yuan provides wording]
Previous resolution [SUPERSEDED]:
This wording is relative to N4878.
Modify 27.11.8 [specialized.construct] as indicated:
template<class T, class... Args> constexpr T* construct_at(T* location, Args&&... args); namespace ranges { template<class T, class... Args> constexpr T* construct_at(T* location, Args&&... args); }-1- Constraints: The expression ::new (declval<void*>()) T(declval<Args>()...) is well-formed when treated as an unevaluated operand.
-2- Effects: Equivalent to:returnauto ptr = ::new (voidify(*location)) T(std::forward<Args>(args)...); if constexpr (is_array_v<T>) return launder(location); else return ptr;
[2021-12-07; Zhihao Yuan comments and provides improved wording]
The previous PR allows constructing arbitrary number of elements when T is an array of unknown bound:
extern int a[]; std::construct_at(&a, 0, 1, 2);
and leads to a UB.
Proposed resolution:
This wording is relative to N4901.
Modify 27.11.8 [specialized.construct] as indicated:
template<class T, class... Args> constexpr T* construct_at(T* location, Args&&... args); namespace ranges { template<class T, class... Args> constexpr T* construct_at(T* location, Args&&... args); }-1- Constraints: The expression ::new (declval<void*>()) T(declval<Args>()...) is well-formed when treated as an unevaluated operand (7.2.3 [expr.context]) and is_unbounded_array_v<T> is false.
-2- Effects: Equivalent to:returnauto ptr = ::new (voidify(*location)) T(std::forward<Args>(args)...); if constexpr (is_array_v<T>) return launder(location); else return ptr;