From 2bec3ccd4e29860b9467a1e6c0069f2877b7c588 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 31 May 2025 19:10:19 +0200 Subject: [PATCH] clean-up: make `ScopedPtrVect` move-assignable to use it in STL containers This was a pre-C++11 implementation, and at that time, I developed the ScopedHolder to allow handling non-copyable objects in STL containers Meanwhile we have move semantics to achieve the same goal; and since `ScopedPtrVect` shall be retained, it should be upgraded, using the copy-and-swap approach --- src/lib/scoped-ptrvect.hpp | 20 ++++- tests/library/scoped-ptrvect-test.cpp | 44 ++++++++- wiki/thinkPad.ichthyo.mm | 124 +++++++++++++++++++++++++- 3 files changed, 183 insertions(+), 5 deletions(-) diff --git a/src/lib/scoped-ptrvect.hpp b/src/lib/scoped-ptrvect.hpp index c00456b31..5dd87678d 100644 --- a/src/lib/scoped-ptrvect.hpp +++ b/src/lib/scoped-ptrvect.hpp @@ -22,6 +22,7 @@ ** Some details to note: ** - contained objects accessed by reference, never NULL. ** - the exposed iterator automatically dereferences + ** - can be move-assigned and move constructed, like `unique_ptr` ** ** @warning deliberately **not threadsafe** ** @remark This library class provides the same basic functionality as @@ -64,7 +65,7 @@ namespace lib { */ template class ScopedPtrVect - : util::NonCopyable + : util::MoveAssign { using _Vec = std::vector; using VIter = typename _Vec::iterator; @@ -101,6 +102,23 @@ namespace lib { vec_.reserve (capacity); } + ScopedPtrVect (ScopedPtrVect && src) + : vec_{std::move (src.vec_)} + { } + + friend void + swap (ScopedPtrVect& left, ScopedPtrVect& right) + { + swap (left.vec_, right.vec_); + } + + ScopedPtrVect& + operator= (ScopedPtrVect && other) + { + swap (*this, other); + return *this; + } + /** take ownership of the given object, * adding it at the end of the collection diff --git a/tests/library/scoped-ptrvect-test.cpp b/tests/library/scoped-ptrvect-test.cpp index c8bfb6307..b14a3cba8 100644 --- a/tests/library/scoped-ptrvect-test.cpp +++ b/tests/library/scoped-ptrvect-test.cpp @@ -51,6 +51,7 @@ namespace test{ simpleUsage(); iterating(); detaching(); + moving(); } @@ -145,7 +146,7 @@ namespace test{ detaching() { int id2, id3; - Dummy* extracted(0); + Dummy* extracted{nullptr}; CHECK (0 == Dummy::checksum()); { VectD holder; @@ -177,6 +178,47 @@ namespace test{ delete extracted; CHECK (0 == Dummy::checksum()); } + + + void + moving() + { { + VectD org; + VectD left; + CHECK (0 == Dummy::checksum()); + + org.manage (new Dummy); + org.manage (new Dummy); + org.manage (new Dummy); + + CHECK (not isnil (org)); + CHECK ( isnil (left)); + auto sum = Dummy::checksum(); + CHECK (sum > 0); + int id0 = org[0].getVal(), + id1 = org[1].getVal(), + id2 = org[2].getVal(); + + // create by move + VectD right{std::move (org)}; + CHECK ( isnil (org)); + CHECK ( isnil (left)); + CHECK (not isnil (right)); + CHECK (sum == Dummy::checksum()); + + // move-assignment + left = std::move (right); + CHECK ( isnil (org)); + CHECK (not isnil (left)); + CHECK ( isnil (right)); + CHECK (sum == Dummy::checksum()); + CHECK (id0 == left[0].getVal()); + CHECK (id1 == left[1].getVal()); + CHECK (id2 == left[2].getVal()); + + } + CHECK (0 == Dummy::checksum()); + } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index e45fc2ba5..7efa2c6d8 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -52278,7 +52278,7 @@ - + @@ -163658,7 +163658,8 @@ Since then others have made contributions, see the log for the history. - + + @@ -163679,7 +163680,8 @@ Since then others have made contributions, see the log for the history. - + + @@ -163711,6 +163713,122 @@ Since then others have made contributions, see the log for the history. + + + + + + + + + + + + + + + +

+ allein schon wenn man so viel Kommentar zur Rechtfertigung schreiben muß; und dann ist das Ganze auch noch stateful, und es führte zu einer Erweiterun, ScopedHolderTransfer, mit noch viel mehr Kommentar und Erläuterung und umständlichen Tests (und dann wird das am Ende doch fast nicht verwendet) +

+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + +

+ hatte das zwar geschaffen, um non-copyable Objekte in einen Vector packen zu können — aber es ist kein Container, sondern lediglich ein inline-Buffer +

+ + +
+ + +
+ + + + + + + + + + + +

+ für einen Test / Diagnose-Container ist das in der Tat sinnvoll, denn man möchte da nicht die Komplexität mit der Verwaltung von Extents  haben (größere Speicherblöcke, aus denen dann kleinere Allokationen ausgegeben werden) +

+ + +
+ +
+ + + + + + + + + +

+ dann könnte man ihn nämlich ohne weiteres direkt in jedem STL-Container per emplace einbringen, selbst in std::vector +

+ + +
+ +
+ + + + + + +

+ unique_ptr kann das ja auc +

+ + +
+ + + + + +
+
+ + + + + + + +