diff --git a/src/lib/scoped-collection.hpp b/src/lib/scoped-collection.hpp index b9174401b..2c9f85d7a 100644 --- a/src/lib/scoped-collection.hpp +++ b/src/lib/scoped-collection.hpp @@ -257,6 +257,33 @@ namespace lib { throw; } } + /** variation of RAII-style: using a builder function, + * which is a member of some object. This supports the + * typical usage situation, where a manager object builds + * a ScopedCollection of some components + * @param builder member function used to create the elements + * @param instance the owning class instance, on which the + * builder member function will be invoked ("this"). + */ + template + ScopedCollection (size_t maxElements, void (TY::*builder) (ElementHolder&), TY * const instance) + : level_(0) + , capacity_(maxElements) + , elements_(new ElementHolder[maxElements]) + { + try { + while (level_ < capacity_) + { + ElementHolder& storageFrame (elements_[level_]); + (instance->*builder) (storageFrame); + ++level_; + }} + catch(...) + { + clear(); + throw; + } } + /* == some pre-defined Builders == */ class FillAll; ///< fills the ScopedCollection with default constructed I-instances diff --git a/tests/lib/scoped-collection-test.cpp b/tests/lib/scoped-collection-test.cpp index 76c76c12e..f112e79da 100644 --- a/tests/lib/scoped-collection-test.cpp +++ b/tests/lib/scoped-collection-test.cpp @@ -111,6 +111,7 @@ namespace test{ iterating(); verify_defaultPopulator(); verify_iteratorPopulator(); + verify_embeddedCollection(); } @@ -416,6 +417,54 @@ namespace test{ // note: the iterator is assumed to deliver a sufficient amount of elements VERIFY_ERROR (ITER_EXHAUST, CollI (50, CollI::pull (source.begin()))); } + + + /** @test simulate the typical situation of a manager + * owning some embedded components. Here, our ManagerDemo + * instance owns a collection of numbers 50..1. They are + * created right while initialising the manager, and this + * initialisation is done by invoking a member function + * of the manager + */ + void + verify_embeddedCollection() + { + ManagerDemo object_with_embedded_Collection(50); + CHECK (sum(50) == object_with_embedded_Collection.useMyNumbers()); + } + + class ManagerDemo + { + typedef ScopedCollection CollI; + + uint memberVar_; + const CollI my_own_Numbers_; + + void + buildNumbers (CollI::ElementHolder& storage) + { + storage.create(memberVar_); + --memberVar_; + } + + public: + ManagerDemo(uint cnt) + : memberVar_(cnt) + , my_own_Numbers_(cnt, &ManagerDemo::buildNumbers, this) + { + CHECK (0 == memberVar_); + CHECK (cnt == my_own_Numbers_.size()); + } + + uint + useMyNumbers() + { + uint sum(0); + for (CollI::const_iterator ii = my_own_Numbers_.begin(); ii; ++ii) + sum += *ii; + return sum; + } + }; };