convert ScopedCollection to rely on C++11

- variadic templates
- type traits
- use uniqe_ptr to manage storage (instead of boost::scoped_array)
This commit is contained in:
Fischlurch 2017-08-06 18:21:25 +02:00
parent 0b621e71c5
commit 70e1a5b922
2 changed files with 34 additions and 170 deletions

View file

@ -42,8 +42,8 @@
** ctor just to specify the maximum size). The storage to hold up to this
** number of objects is (heap) allocated right away, but no objects are
** created. Later on, individual objects are "pushed" into the collection
** by invoking #appendNewElement() to create a new element of the default
** type `I`) or #appendNew<Type>(args) to create some subtype. This way,
** by invoking #emplaceElement() to create a new element of the default
** type `I`) or #emplace<Type>(args) to create some subtype. This way,
** the container is being filled successively.
** - the "RAII style" usage strives to create all of the content objects
** right away, immediately after the memory allocation. This usage pattern
@ -73,10 +73,7 @@
#include "lib/iter-adapter.hpp"
#include <boost/noncopyable.hpp>
#include <boost/scoped_array.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <type_traits>
namespace lib {
@ -134,83 +131,18 @@ namespace lib {
#define TYPE_AND_STORAGE_SANITY_CHECK \
BOOST_STATIC_ASSERT (((boost::is_same<I,TY>::value \
||boost::is_base_of<I,TY>::value)\
&& sizeof(TY) <= siz))
/** Abbreviation for placement new */
#define EMBEDDED_ELEMENT_CTOR(_CTOR_CALL_) \
TYPE_AND_STORAGE_SANITY_CHECK; \
return *new(&buf_) _CTOR_CALL_; \
template<class TY>
/** place object of type TY, forwarding ctor arguments */
template<class TY, typename...ARGS>
TY&
create ()
create (ARGS&& ...args)
{
EMBEDDED_ELEMENT_CTOR ( TY() )
static_assert ( (std::is_same<I,TY>::value
||std::is_base_of<I,TY>::value)
&& sizeof(TY) <= siz,
"ElementHolder buffer to small");
return *new(&buf_) TY (std::forward<ARGS> (args)...);
}
template<class TY, typename A1>
TY& //___________________________________________
create (A1 a1) ///< place object of type TY, using 1-arg ctor
{
EMBEDDED_ELEMENT_CTOR ( TY(a1) )
}
template< class TY
, typename A1
, typename A2
>
TY& //___________________________________________
create (A1 a1, A2 a2) ///< place object of type TY, using 2-arg ctor
{
EMBEDDED_ELEMENT_CTOR ( TY(a1,a2) )
}
template< class TY
, typename A1
, typename A2
, typename A3
>
TY& //___________________________________________
create (A1 a1, A2 a2, A3 a3) ///< place object of type TY, using 3-arg ctor
{
EMBEDDED_ELEMENT_CTOR ( TY(a1,a2,a3) )
}
template< class TY
, typename A1
, typename A2
, typename A3
, typename A4
>
TY& //___________________________________________
create (A1 a1, A2 a2, A3 a3, A4 a4) ///< place object of type TY, using 4-arg ctor
{
EMBEDDED_ELEMENT_CTOR ( TY(a1,a2,a3,a4) )
}
template< class TY
, typename A1
, typename A2
, typename A3
, typename A4
, typename A5
>
TY& //___________________________________________
create (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) ///< place object of type TY, using 5-arg ctor
{
EMBEDDED_ELEMENT_CTOR ( TY(a1,a2,a3,a4,a5) )
}
#undef TYPE_AND_STORAGE_SANITY_CHECK
#undef EMBEDDED_ELEMENT_CTOR
};
@ -362,94 +294,26 @@ namespace lib {
///////////////////////////////////////////////////////TICKET #967 : the following can be written better now. Also should be named 'emplace'
/** push a new element of default type
* to the end of this container
* @note EX_STRONG */
I& appendNewElement() { return appendNew<I>(); }
template< class TY >
TY& //_________________________________________
appendNew () ///< add object of type TY, using 0-arg ctor
I&
emplaceElement()
{
__ensureSufficientCapacity();
TY& newElm = elements_[level_].template create<TY>();
++level_;
return newElm;
return emplace<I>();
}
template< class TY
, typename A1
>
TY& //_________________________________________
appendNew (A1 a1) ///< add object of type TY, using 1-arg ctor
/**
* push new entry at the end of this container
* and build object of type TY in place there
*/
template<class TY, typename...ARGS>
TY&
emplace (ARGS&& ...args)
{
__ensureSufficientCapacity();
TY& newElm = elements_[level_].template create<TY>(a1);
++level_;
return newElm;
}
template< class TY
, typename A1
, typename A2
>
TY& //_________________________________________
appendNew (A1 a1, A2 a2) ///< add object of type TY, using 2-arg ctor
{
__ensureSufficientCapacity();
TY& newElm = elements_[level_].template create<TY>(a1,a2);
++level_;
return newElm;
}
template< class TY
, typename A1
, typename A2
, typename A3
>
TY& //_________________________________________
appendNew (A1 a1, A2 a2, A3 a3) ///< add object of type TY, using 3-arg ctor
{
__ensureSufficientCapacity();
TY& newElm = elements_[level_].template create<TY>(a1,a2,a3);
++level_;
return newElm;
}
template< class TY
, typename A1
, typename A2
, typename A3
, typename A4
>
TY& //_________________________________________
appendNew (A1 a1, A2 a2, A3 a3, A4 a4) ///< add object of type TY, using 4-arg ctor
{
__ensureSufficientCapacity();
TY& newElm = elements_[level_].template create<TY>(a1,a2,a3,a4);
++level_;
return newElm;
}
template< class TY
, typename A1
, typename A2
, typename A3
, typename A4
, typename A5
>
TY& //_________________________________________
appendNew (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) ///< add object of type TY, using 5-arg ctor
{
__ensureSufficientCapacity();
TY& newElm = elements_[level_].template create<TY>(a1,a2,a3,a4,a5);
TY& newElm = elements_[level_].template create<TY>(std::forward<ARGS> (args)...);
++level_;
return newElm;
}
@ -489,7 +353,7 @@ namespace lib {
private:
/* ==== Storage: heap allocated array of element buffers ==== */
typedef boost::scoped_array<ElementHolder> ElementStorage;
typedef std::unique_ptr<ElementHolder[]> ElementStorage;
size_t level_;
size_t capacity_;

View file

@ -157,7 +157,7 @@ namespace test{
{
CollD coll(50);
for (uint i=0; i<coll.capacity(); ++i)
coll.appendNew<Dummy>(i);
coll.emplace<Dummy>(i);
int check=0;
CollD::iterator ii = coll.begin();
@ -235,28 +235,28 @@ namespace test{
CHECK (0 == coll.size());
CHECK (0 == Dummy::checksum());
Dummy& d0 = coll.appendNewElement();
Dummy& d0 = coll.emplaceElement();
CHECK (1 == coll.size());
Dummy& d1 = coll.appendNew<Dummy> (rr);
Dummy& d1 = coll.emplace<Dummy> (rr);
CHECK (2 == coll.size());
int sum = Dummy::checksum();
// trigger the bomb
VERIFY_ERROR (SUBVERSIVE, coll.appendNew<SubDummy>(rr,rr) );
VERIFY_ERROR (SUBVERSIVE, coll.emplace<SubDummy>(rr,rr) );
CHECK ( 2 == coll.size()); // the other objects survived
CHECK (sum == Dummy::checksum());
Dummy& d2 = coll.appendNew<SubDummy> (rr, rr+1);
Dummy& d2 = coll.emplace<SubDummy> (rr, rr+1);
CHECK (3 == coll.size());
CHECK (sum + rr == Dummy::checksum());
VERIFY_ERROR (CAPACITY, coll.appendNewElement());
VERIFY_ERROR (CAPACITY, coll.appendNewElement());
VERIFY_ERROR (CAPACITY, coll.appendNewElement());
VERIFY_ERROR (CAPACITY, coll.emplaceElement());
VERIFY_ERROR (CAPACITY, coll.emplaceElement());
VERIFY_ERROR (CAPACITY, coll.emplaceElement());
CHECK (3 == coll.size());
CHECK (sum + rr == Dummy::checksum());
@ -269,7 +269,7 @@ namespace test{
// returns the trigger value, when the argument is zero
coll.clear();
coll.appendNew<SubDummy> (11,22);
coll.emplace<SubDummy> (11,22);
CHECK ( 1 == coll.size());
CHECK (11 == Dummy::checksum());
@ -426,7 +426,7 @@ namespace test{
CollI source (25);
for (uint i=0; i < source.capacity(); ++i)
source.appendNew<uint>(i); // holding the numbers 0..24
source.emplace<uint>(i); // holding the numbers 0..24
CollI coll (20, CollI::pull(source.begin()));
// this immediately pulls in the first 20 elements