libstdc++: Fix std::to_array for trivial-ish types [PR115522]
Due to PR c++/85723 the std::is_trivial trait is true for types with a deleted default constructor, so the use of std::is_trivial in std::to_array is not sufficient to ensure the type can be trivially default constructed then filled using memcpy. I also forgot that a type with a deleted assignment operator can still be trivial, so we also need to check that it's assignable because the is_constant_evaluated() path can't use memcpy. Replace the uses of std::is_trivial with std::is_trivially_copyable (needed for memcpy), std::is_trivially_default_constructible (needed so that the default construction is valid and does no work) and std::is_copy_assignable (needed for the constant evaluation case). libstdc++-v3/ChangeLog: PR libstdc++/115522 * include/std/array (to_array): Workaround the fact that std::is_trivial is not sufficient to check that a type is trivially default constructible and assignable. * testsuite/23_containers/array/creation/115522.cc: New test. (cherry picked from commit 510ce5eed69ee1bea9c2c696fe3b2301e16d1486)
This commit is contained in:
parent
cff270707f
commit
21c8708ba6
2 changed files with 39 additions and 2 deletions
|
@ -431,7 +431,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
static_assert(is_constructible_v<_Tp, _Tp&>);
|
||||
if constexpr (is_constructible_v<_Tp, _Tp&>)
|
||||
{
|
||||
if constexpr (is_trivial_v<_Tp>)
|
||||
if constexpr (is_trivially_copyable_v<_Tp>
|
||||
&& is_trivially_default_constructible_v<_Tp>
|
||||
&& is_copy_assignable_v<_Tp>)
|
||||
{
|
||||
array<remove_cv_t<_Tp>, _Nm> __arr;
|
||||
if (!__is_constant_evaluated() && _Nm != 0)
|
||||
|
@ -460,7 +462,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
static_assert(is_move_constructible_v<_Tp>);
|
||||
if constexpr (is_move_constructible_v<_Tp>)
|
||||
{
|
||||
if constexpr (is_trivial_v<_Tp>)
|
||||
if constexpr (is_trivially_copyable_v<_Tp>
|
||||
&& is_trivially_default_constructible_v<_Tp>
|
||||
&& is_copy_assignable_v<_Tp>)
|
||||
{
|
||||
array<remove_cv_t<_Tp>, _Nm> __arr;
|
||||
if (!__is_constant_evaluated() && _Nm != 0)
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// { dg-do compile { target c++20 } }
|
||||
|
||||
// PR libstdc++/115522 std::to_array no longer works for struct which is
|
||||
// trivial but not default constructible
|
||||
|
||||
#include <array>
|
||||
|
||||
void
|
||||
test_deleted_ctor()
|
||||
{
|
||||
struct S
|
||||
{
|
||||
S() = delete;
|
||||
S(int) { }
|
||||
};
|
||||
|
||||
S arr[1] = {{1}};
|
||||
auto arr1 = std::to_array(arr);
|
||||
auto arr2 = std::to_array(std::move(arr));
|
||||
}
|
||||
|
||||
void
|
||||
test_deleted_assignment()
|
||||
{
|
||||
struct S
|
||||
{
|
||||
void operator=(const S&) = delete;
|
||||
};
|
||||
|
||||
S arr[1] = {};
|
||||
auto a1 = std::to_array(arr);
|
||||
auto a2 = std::to_array(std::move(arr));
|
||||
}
|
Loading…
Add table
Reference in a new issue