sharedVector more c++11

support std::move() and construct
from initializer list.
This commit is contained in:
Michael Davidsaver
2018-01-04 10:28:34 -08:00
parent 0b6b01ef83
commit 09574c0e82
2 changed files with 213 additions and 43 deletions

View File

@@ -15,6 +15,10 @@
#include <stdexcept>
#include <iterator>
#if __cplusplus>=201103L
# include <initializer_list>
#endif
#include <cassert>
#include "pv/sharedPtr.h"
@@ -70,18 +74,24 @@ namespace detail {
*/
public:
#if __cplusplus>=201103L
//! @brief Empty vector (not very interesting)
constexpr shared_vector_base() noexcept
:m_sdata(), m_offset(0), m_count(0), m_total(0)
{}
#else
//! @brief Empty vector (not very interesting)
shared_vector_base()
:m_sdata(), m_offset(0), m_count(0), m_total(0)
{}
#endif
protected:
// helper for constructors
// Ensure that offset and size are zero when we are constructed with NULL
void _null_input()
{
if(!m_sdata.get()) {
if(!m_sdata) {
m_offset = m_total = m_count = 0;
} else {
// ensure we won't have integer overflows later
@@ -90,19 +100,12 @@ namespace detail {
}
public:
#ifdef _WIN32
template<typename A>
shared_vector_base(A* v, size_t o, size_t c)
:m_sdata(v, detail::default_array_deleter<A*>())
,m_offset(o), m_count(c), m_total(c)
{_null_input();}
#else
template<typename A>
shared_vector_base(A v, size_t o, size_t c)
:m_sdata(v, detail::default_array_deleter<A>())
,m_offset(o), m_count(c), m_total(c)
{_null_input();}
#endif
shared_vector_base(const std::tr1::shared_ptr<E>& d, size_t o, size_t c)
:m_sdata(d), m_offset(o), m_count(c), m_total(c)
{_null_input();}
@@ -118,6 +121,17 @@ namespace detail {
,m_count(O.m_count), m_total(O.m_total)
{}
#if __cplusplus >= 201103L
shared_vector_base(shared_vector_base &&O)
:m_sdata(std::move(O.m_sdata))
,m_offset(O.m_offset)
,m_count(O.m_count)
,m_total(O.m_total)
{
O.clear();
}
#endif
protected:
typedef typename meta::strip_const<E>::type _E_non_const;
public:
@@ -132,7 +146,11 @@ namespace detail {
{
if(!O.unique())
throw std::runtime_error("Can't freeze non-unique vector");
#if __cplusplus >= 201103L
m_sdata = std::move(O.m_sdata);
#else
m_sdata = O.m_sdata;
#endif
O.clear();
}
@@ -146,7 +164,11 @@ namespace detail {
,m_total(O.m_total)
{
O.make_unique();
#if __cplusplus >= 201103L
m_sdata = std::move(std::tr1::const_pointer_cast<E>(O.m_sdata));
#else
m_sdata = std::tr1::const_pointer_cast<E>(O.m_sdata);
#endif
O.clear();
}
@@ -162,6 +184,21 @@ namespace detail {
return *this;
}
#if __cplusplus >= 201103L
//! @brief Move an existing vector
shared_vector_base& operator=(shared_vector_base&& o)
{
if(&o!=this) {
m_sdata=std::move(o.m_sdata);
m_offset=o.m_offset;
m_count=o.m_count;
m_total=o.m_total;
o.clear();
}
return *this;
}
#endif
//! @brief Swap the contents of this vector with another
void swap(shared_vector_base& o) {
if(&o!=this) {
@@ -180,11 +217,12 @@ namespace detail {
}
//! @brief Data is not shared?
bool unique() const {return !m_sdata || m_sdata.unique();}
bool unique() const {return !m_sdata || m_sdata.use_count()<=1;}
//! @brief Number of elements visible through this vector
size_t size() const{return m_count;}
//! @brief shorthand for size()==0
bool empty() const{return !m_count;}
@@ -272,9 +310,22 @@ public:
// allow specialization for all E to be friends
template<typename E1, class Enable1> friend class shared_vector;
//! @brief Empty vector (not very interesting)
#if __cplusplus>=201103L
constexpr shared_vector() noexcept :base_t() {}
#else
shared_vector() :base_t() {}
#endif
#if __cplusplus>=201103L
template<typename A>
shared_vector(std::initializer_list<A> L)
:base_t(new _E_non_const[L.size()], 0, L.size())
{
_E_non_const *raw = const_cast<_E_non_const*>(data());
std::copy(L.begin(), L.end(), raw);
}
#endif
//! @brief Allocate (with new[]) a new vector of size c
explicit shared_vector(size_t c)
@@ -321,6 +372,11 @@ public:
//! @brief Copy an existing vector of same type
shared_vector(const shared_vector& o) :base_t(o) {}
#if __cplusplus>=201103L
//! @brief Move an existing vector of same type
shared_vector(shared_vector&& o) :base_t(std::move(o)) {}
#endif
//! @internal
//! Internal for static_shared_vector_cast
template<typename FROM>
@@ -342,6 +398,20 @@ public:
:base_t(O,t)
{}
inline shared_vector& operator=(const shared_vector& o)
{
this->base_t::operator=(o);
return *this;
}
#if __cplusplus>=201103L
inline shared_vector& operator=(shared_vector&& o)
{
this->base_t::operator=(std::move(o));
return *this;
}
#endif
size_t max_size() const{return ((size_t)-1)/sizeof(E);}
size_t capacity() const { return this->m_total; }
@@ -353,6 +423,9 @@ public:
* does not increase.
*
* For notes on copying see docs for make_unique().
*
* @throws std::bad_alloc if requested allocation can not be made
* @throws other exceptions from element copy ctor
*/
void reserve(size_t i) {
if(this->unique() && i<=this->m_total)
@@ -377,13 +450,16 @@ public:
* as if make_unique() were called. This holds even if the size does not change.
*
* For notes on copying see docs for make_unique().
*
* @throws std::bad_alloc if requested allocation can not be made
* @throws other exceptions from element copy ctor
*/
void resize(size_t i) {
if(i==this->m_count) {
make_unique();
return;
}
if(this->m_sdata && this->m_sdata.unique()) {
if(this->m_sdata && this->m_sdata.use_count()==1) {
// we have data and exclusive ownership of it
if(i<=this->m_total) {
// We have room to grow (or shrink)!
@@ -438,10 +514,14 @@ public:
}
assert(original.unique());
@endcode
*
* @throws std::bad_alloc if requested allocation can not be made
* @throws other exceptions from element copy ctor
*/
void make_unique() {
if(this->unique())
return;
// at this point we know that !!m_sdata, so get()!=NULL
_E_non_const *d = new _E_non_const[this->m_total];
try {
std::copy(this->m_sdata.get()+this->m_offset,
@@ -527,10 +607,15 @@ public:
// data access
//! @brief Return Base pointer
pointer data() const{return this->m_sdata.get()+this->m_offset;}
//! @brief Member access
//! Undefined if empty()==true.
reference operator[](size_t i) const {return this->m_sdata.get()[this->m_offset+i];}
//! @brief Member access
//! @throws std::out_of_range if i>=size().
reference at(size_t i) const
{
if(i>this->m_count)
@@ -577,7 +662,11 @@ public:
typedef std::tr1::shared_ptr<E> shared_pointer_type;
#if __cplusplus>=201103L
constexpr shared_vector() noexcept :base_t(), m_vtype((ScalarType)-1) {}
#else
shared_vector() :base_t(), m_vtype((ScalarType)-1) {}
#endif
shared_vector(pointer v, size_t o, size_t c)
:base_t(v,o,c), m_vtype((ScalarType)-1) {}
@@ -593,6 +682,11 @@ public:
shared_vector(const shared_vector& o)
:base_t(o), m_vtype(o.m_vtype) {}
#if __cplusplus>=201103L
shared_vector(shared_vector&& o)
:base_t(std::move(o)), m_vtype(o.m_vtype) {}
#endif
//! @internal
//! Internal for static_shared_vector_cast
template<typename FROM>
@@ -623,6 +717,17 @@ public:
return *this;
}
#if __cplusplus>=201103L
shared_vector& operator=(shared_vector&& o)
{
if(&o!=this) {
this->base_t::operator=(std::move(o));
m_vtype = o.m_vtype;
}
return *this;
}
#endif
size_t max_size() const{return (size_t)-1;}
pointer data() const{