From 286c2d4d2a3dea1283192a4fd46ea4e0cbda78fe Mon Sep 17 00:00:00 2001 From: Ole Erik Peistorpet Date: Thu, 6 Jun 2024 12:09:48 +0200 Subject: [PATCH] explicit dynarray copy constructor and clone function Also operator =(const dynarray &&) = delete --- dynarray.h | 9 +++++++-- .../dynarray_construct_assignop_swap_gtest.cpp | 15 +++++++++++++++ unit_test/dynarray_mutate_gtest.cpp | 6 +++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/dynarray.h b/dynarray.h index f8ba76ff..434ac161 100644 --- a/dynarray.h +++ b/dynarray.h @@ -101,9 +101,13 @@ class dynarray dynarray(dynarray && other) noexcept : _m(std::move(other._m)) {} dynarray(dynarray && other, Alloc a); - dynarray(const dynarray & other) : dynarray(other, + explicit dynarray(const dynarray & other) : dynarray(other, _alloTrait::select_on_container_copy_construction(other._m)) {} - dynarray(const dynarray & other, Alloc a) : _m(a) { append(other); } + explicit dynarray(const dynarray & other, Alloc a) : _m(a) { append(other); } + + //! Workaround for GCC failing to choose explicit copy constructor in some cases + friend dynarray clone(const dynarray & d) { return dynarray(d); } + friend dynarray clone(const dynarray & d, Alloc a) { return dynarray(d, std::move(a)); } ~dynarray() noexcept; @@ -111,6 +115,7 @@ class dynarray noexcept(_alloTrait::propagate_on_container_move_assignment::value or _alloTrait::is_always_equal::value); //! Requires that allocator_type is always equal or does not have propagate_on_container_copy_assignment dynarray & operator =(const dynarray & other) &; + dynarray & operator =(const dynarray &&) = delete; dynarray & operator =(std::initializer_list il) & { assign(il); return *this; } diff --git a/unit_test/dynarray_construct_assignop_swap_gtest.cpp b/unit_test/dynarray_construct_assignop_swap_gtest.cpp index b84ff886..d9c27a8b 100644 --- a/unit_test/dynarray_construct_assignop_swap_gtest.cpp +++ b/unit_test/dynarray_construct_assignop_swap_gtest.cpp @@ -662,6 +662,21 @@ TEST_F(dynarrayConstructTest, copyConstructThrowing) } #endif +TEST_F(dynarrayConstructTest, clone) +{ + using Al = StatefulAllocator; + auto x = dynarray< TrivialRelocat, Al >({TrivialRelocat{0.5}}, Al(-5)); + EXPECT_EQ(1, g_allocCount.nAllocations); + + auto y = clone(x); + EXPECT_EQ(-5, y.get_allocator().id); + EXPECT_EQ(2, g_allocCount.nAllocations); + + auto z = clone(y, Al(7)); + EXPECT_EQ(0.5, *z.front()); + EXPECT_EQ(3, g_allocCount.nAllocations); +} + TEST_F(dynarrayConstructTest, swap) { dynarrayTrackingAlloc a, b{1, 2}; diff --git a/unit_test/dynarray_mutate_gtest.cpp b/unit_test/dynarray_mutate_gtest.cpp index f75eb1bb..d76dcc7e 100644 --- a/unit_test/dynarray_mutate_gtest.cpp +++ b/unit_test/dynarray_mutate_gtest.cpp @@ -831,7 +831,11 @@ TEST_F(dynarrayTest, erasePrecondCheck) leakDetector->enabled = false; dynarray di{-2}; - auto copy = di; +#if !defined __GNUC__ or __GNUC__ < 12 + auto copy = dynarray(di); +#else + auto copy = clone(di); +#endif ASSERT_DEATH( copy.erase(di.begin()), "" ); }