diff --git a/src/lib/ref-array-impl.hpp b/src/lib/ref-array-impl.hpp index 9cf5226f7..c948b9b2c 100644 --- a/src/lib/ref-array-impl.hpp +++ b/src/lib/ref-array-impl.hpp @@ -33,7 +33,8 @@ ** storage of variant-records, able to hold a mixture of subclasses. (the latter cases ** will be implemented when needed). ** - ** @warning in rework 5/2025 + ** @deprecated 5/2025 to be reworked and obsoleted — do not use further + ** @see several-builder.hpp ** @see ref-array-test.cpp ** */ diff --git a/src/lib/ref-array.hpp b/src/lib/ref-array.hpp index 13b90f9c3..7cd30a664 100644 --- a/src/lib/ref-array.hpp +++ b/src/lib/ref-array.hpp @@ -25,7 +25,8 @@ ** Abstraction interface: array-like access by subscript ** @todo as of 2016, this concept seems very questionable: do we _really_ want ** to abstract over random access, or do we _actually_ want for-iteration?? - ** @warning in rework 5/2025 + ** @deprecated 5/2025 to be obsoleted by a similar design + ** @see several.hpp */ diff --git a/src/lib/several-builder.hpp b/src/lib/several-builder.hpp new file mode 100644 index 000000000..ac172aa31 --- /dev/null +++ b/src/lib/several-builder.hpp @@ -0,0 +1,176 @@ +/* + SEVERAL-BUILDER.hpp - builder for a limited fixed collection of elements + + Copyright (C) Lumiera.org + 2024, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file several-builder.hpp + ** Some (library-) implementations of the RefArray interface. + ** + ** Being an array-like object exposing just a const ref, it is typically used + ** on interfaces, and the type of the array "elements" usually is a ABC or interface. + ** The actual implementation typically holds a subclass, and is either based on a vector, + ** or a fixed storage contained within the implementation. The only price to pay is + ** a virtual call on element access. + ** + ** For advanced uses it would be possible to have a pointer-array or even an embedded + ** storage of variant-records, able to hold a mixture of subclasses. (the latter cases + ** will be implemented when needed). + ** + ** @warning WIP and in rework 5/2025 -- not clear yet where this design leads to... + ** @see several-builder-test.cpp + ** + */ + + +#ifndef LIB_SEVERAL_BUILDER_H +#define LIB_SEVERAL_BUILDER_H + + +#include "lib/several.hpp" +#include "include/logging.h" + +#include +using std::vector; + + + +namespace lib { + + /** + * Wrap a vector holding objects of a subtype and + * provide array-like access using the interface type. + */ + template + class RefArrayVectorWrapper + : public RefArray + { + typedef vector const& Tab; + Tab table_; + + public: + + RefArrayVectorWrapper (Tab toWrap) + : table_(toWrap) + { } + + virtual size_t size() const + { + return table_.size(); + } + + virtual B const& operator[] (size_t i) const + { + REQUIRE (i < size()); + return table_[i]; + } + }; + + + /** + * This variation of the wrapper actually + * \em is a vector, but can act as a RefArray + */ + template + class RefArrayVector + : public vector, + public RefArrayVectorWrapper + { + typedef RefArrayVectorWrapper Wrap; + typedef vector Vect; + typedef typename Vect::size_type Size_t; + typedef typename Vect::value_type Val_t; + + public: + RefArrayVector() : Vect(), Wrap((Vect&)*this) {} + RefArrayVector(Size_t n, Val_t const& v = Val_t()) : Vect(n,v), Wrap((Vect&)*this) {} + RefArrayVector(Vect const& ref) : Vect(ref), Wrap((Vect&)*this) {} + + using Vect::size; + using Wrap::operator[]; + }; + + + + /** + * RefArray implementation based on a fixed size array, + * i.e. the storage is embedded. Embedded subclass obj + * either need to be default constructible or be + * placed directly by a factory + */ + template + class RefArrayTable + : public RefArray + { + char storage_[n*sizeof(IM)]; + IM* array_; + + public: + RefArrayTable() ///< objects created in-place by default ctor + : array_ (reinterpret_cast (&storage_)) + { + size_t i=0; + try + { + while (i + RefArrayTable(FAC& factory) ///< objects created in-place by factory + : array_ (reinterpret_cast (&storage_)) + { + size_t i=0; + try + { + while (i + 2024, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file several.hpp + ** Abstraction interface: array-like access by subscript + ** @todo as of 2016, this concept seems very questionable: do we _really_ want + ** to abstract over random access, or do we _actually_ want for-iteration?? + ** @warning WIP-WIP-WIP in rework 5/2025 + ** @see several-builder.hpp + */ + + +#ifndef LIB_SEVERAL_H +#define LIB_SEVERAL_H + + +#include "lib/nocopy.hpp" + + +namespace lib { + + /** + * Abstraction: Array of const references. + * Typically the return type is an interface, + * and the Implementation wraps some datastructure + * holding subclasses. + * @todo ouch -- a collection that isn't iterable... ///////////////////////TICKET #1040 + * @warning in rework 5/2025 + */ + template + class RefArray + : util::NonCopyable + { + public: + virtual ~RefArray() {} ///< this is an interface + + virtual T const& operator[] (size_t i) const =0; + virtual size_t size() const =0; + }; + + +} // namespace lib +#endif diff --git a/tests/15library.tests b/tests/15library.tests index f0c471116..ff41d023e 100644 --- a/tests/15library.tests +++ b/tests/15library.tests @@ -598,6 +598,11 @@ return: 0 END +PLANNED "Several elements" SeveralBuilder_test < + 2024, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + +/** @file several-builder-test.cpp + ** unit test \ref SeveralBuilder_test + */ + + +#include "lib/test/run.hpp" +#include "lib/util.hpp" + +#include "lib/several-builder.hpp" + +#include + +using ::test::Test; +using std::vector; +using std::rand; + + +namespace lib { +namespace test{ + + + namespace { // test types + + struct I + { + virtual int op(int i) const =0; + virtual ~I() {} + }; + + struct Sub1 : I + { + int offs_; + + Sub1 (int o=1) : offs_(o) {} + + int op (int i) const { return i+offs_; } + }; + + struct Sub2 : I + { + const char* letterz_; + Sub2() : letterz_("ABCDEFGHIJKLMNOPQRSTUVWXYZ") {} + + int op (int i) const { return (int)letterz_[i % 26]; } + }; + + struct Sub3 : I + { + int id_; + static long sum; + static long trigger; + + Sub3(int id) : id_(id) + { + sum +=id_; + if ( id_ == trigger ) + throw trigger; // fail while in construction + } + ~Sub3() + { + sum -=id_; + } + + int op (int i) const { return i + id_; } + }; + + long Sub3::sum = 0; + long Sub3::trigger = -1; + + + } // (END) test types + + + + + + + + /***************************************************************//** + * @test build several wrappers, each based on a different storage, + * all providing RefArray access to a given vector. The rationale + * for RefArray is to expose just the interface: the data structure + * within the actual implementation holds subclass instances of + * the specified interface. + * - RefArrayVectorWrapper is a ref to an existing vector + * - RefArrayVector subclasses std::vector + * - RefArrayTable holds a fix sized table, i.e. embedded storage + * + * @see several-builder.hpp + */ + class SeveralBuilder_test : public Test + { + + virtual void + run (Arg) + { + checkWrapper(); + checkVector(); + checkTable(); + checkTable_inplaceCreation(); + checkTable_errorHandling(); + } + + + + void + checkWrapper() + { + vector subz(10); + RefArrayVectorWrapper subWrap (subz); + + RefArray & rArr (subWrap); + + CHECK (subWrap.size()==subz.size()); + CHECK (INSTANCEOF(I, &rArr[0])); + for (size_t i=0; i subz(10); + + vector & vect (subz); + RefArray & rArr (subz); + + CHECK (vect.size()==subz.size()); + CHECK (INSTANCEOF(I, &rArr[0])); + for (size_t i=0; i tab; + // creates 20 Sub1-objects in-place + // which are indeed located within the object + CHECK (sizeof(tab) >= 20 * sizeof(Sub1)); + CHECK (ADR(tab) < ADR(tab[19]) && ADR(tab[19]) < ADR(tab) + sizeof(tab)); + + RefArray & rArr (tab); + + CHECK (20 == tab.size()); + CHECK (INSTANCEOF(I, &rArr[0])); + for (size_t i=0; i + struct Fac ///< fabricating a series of subclass instances with varying ctor parameter + { + int offset_; + Fac ( ) : offset_ (0) {} + + void operator() (void* place) + { + CHECK (place); + new(place) SUB (offset_++); // note: varying ctor parameter + } + }; + + + void + checkTable_inplaceCreation() + { + Fac theFact; + RefArrayTable tab (theFact); + RefArray & rArr (tab); + CHECK (30 == tab.size()); + for (size_t i=0; i factory; + RefArrayTable table (factory); + CHECK (Sub3::sum == (29+1)*29/2); + } + CHECK (Sub3::sum == 0); + } + + catch(long id) + { + CHECK (id == Sub3::trigger); + CHECK (Sub3::sum == id); + // meaning: all objects have been cleaned up, + // with the exception of the one hitting the trigger + } } + } + }; + + + + /** Register this test class... */ + LAUNCHER (SeveralBuilder_test, "unit common"); + + + +}} // namespace lib::test diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index a67b042d9..c9d335bd5 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -80949,6 +80949,127 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + + + +

+ ⟹ Konsequenz: zusätzlicher Template-Parameter für das Spacing +

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

+ oder man bekommt eine implizite Runtime +

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

+ wenn die Daten „woanders“ liegen +

+ + +
+
+ + + + + + +

+ ⟹ das Allocator-Problem überträgt sich komplett  auf den Container selber +

+ + +
+ + + + + +

+ warum? weil man dann zwingend im Container selber einen »Slot« mit einem Functor oder Allocator-Pointer rumschleppt — oder doch wieder einen zusätzlichen Instanz-Typ-Tag +

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