implement a basic CompressedPair for internal container usage (removes code dups)

master
Daniel Kolesa 2015-06-13 16:32:03 +01:00
parent 4d97aa7ac2
commit e4738e0368
4 changed files with 237 additions and 193 deletions

View File

@ -207,43 +207,6 @@ struct DefaultDelete<T[]> {
/* box */ /* box */
namespace detail { namespace detail {
template<typename T, typename U, bool = octa::IsEmpty<U>::value>
struct BoxPair;
template<typename T, typename U>
struct BoxPair<T, U, false> { /* non-empty deleter */
T *p_ptr;
private:
U p_del;
public:
template<typename D>
BoxPair(T *ptr, D &&dltr): p_ptr(ptr), p_del(octa::forward<D>(dltr)) {}
U &get_deleter() { return p_del; }
const U &get_deleter() const { return p_del; }
void swap(BoxPair &v) {
octa::swap(p_ptr, v.p_ptr);
octa::swap(p_del, v.p_del);
}
};
template<typename T, typename U>
struct BoxPair<T, U, true>: U { /* empty deleter */
T *p_ptr;
template<typename D>
BoxPair(T *ptr, D &&dltr): U(octa::forward<D>(dltr)), p_ptr(ptr) {}
U &get_deleter() { return *this; }
const U &get_deleter() const { return *this; }
void swap(BoxPair &v) {
octa::swap(p_ptr, v.p_ptr);
}
};
template<typename T> template<typename T>
static int ptr_test(...); static int ptr_test(...);
template<typename T> template<typename T>
@ -315,7 +278,7 @@ public:
Box &operator=(Box &&u) { Box &operator=(Box &&u) {
reset(u.release()); reset(u.release());
p_stor.get_deleter() = octa::forward<D>(u.get_deleter()); p_stor.second() = octa::forward<D>(u.get_deleter());
return *this; return *this;
} }
@ -326,7 +289,7 @@ public:
Box & Box &
> operator=(Box<TT, DD> &&u) { > operator=(Box<TT, DD> &&u) {
reset(u.release()); reset(u.release());
p_stor.get_deleter() = octa::forward<DD>(u.get_deleter()); p_stor.second() = octa::forward<DD>(u.get_deleter());
return *this; return *this;
} }
@ -337,28 +300,28 @@ public:
~Box() { reset(); } ~Box() { reset(); }
octa::AddLvalueReference<T> operator*() const { return *p_stor.p_ptr; } octa::AddLvalueReference<T> operator*() const { return *p_stor.first(); }
Pointer operator->() const { return p_stor.p_ptr; } Pointer operator->() const { return p_stor.first(); }
explicit operator bool() const { explicit operator bool() const {
return p_stor.p_ptr != nullptr; return p_stor.first() != nullptr;
} }
Pointer get() const { return p_stor.p_ptr; } Pointer get() const { return p_stor.first(); }
Dref get_deleter() { return p_stor.get_deleter(); } Dref get_deleter() { return p_stor.second(); }
Dcref get_deleter() const { return p_stor.get_deleter(); } Dcref get_deleter() const { return p_stor.second(); }
Pointer release() { Pointer release() {
Pointer p = p_stor.p_ptr; Pointer p = p_stor.first();
p_stor.p_ptr = nullptr; p_stor.first() = nullptr;
return p; return p;
} }
void reset(Pointer p = nullptr) { void reset(Pointer p = nullptr) {
Pointer tmp = p_stor.p_ptr; Pointer tmp = p_stor.first();
p_stor.p_ptr = p; p_stor.first() = p;
if (tmp) p_stor.get_deleter()(tmp); if (tmp) p_stor.second()(tmp);
} }
void swap(Box &u) { void swap(Box &u) {
@ -366,7 +329,7 @@ public:
} }
private: private:
octa::detail::BoxPair<T, D> p_stor; octa::detail::CompressedPair<T *, D> p_stor;
}; };
namespace detail { namespace detail {
@ -452,7 +415,7 @@ public:
Box &operator=(Box &&u) { Box &operator=(Box &&u) {
reset(u.release()); reset(u.release());
p_stor.get_deleter() = octa::forward<D>(u.get_deleter()); p_stor.second() = octa::forward<D>(u.get_deleter());
return *this; return *this;
} }
@ -464,7 +427,7 @@ public:
Box & Box &
> operator=(Box<TT, DD> &&u) { > operator=(Box<TT, DD> &&u) {
reset(u.release()); reset(u.release());
p_stor.get_deleter() = octa::forward<DD>(u.get_deleter()); p_stor.second() = octa::forward<DD>(u.get_deleter());
return *this; return *this;
} }
@ -476,36 +439,36 @@ public:
~Box() { reset(); } ~Box() { reset(); }
octa::AddLvalueReference<T> operator[](octa::Size idx) const { octa::AddLvalueReference<T> operator[](octa::Size idx) const {
return p_stor.p_ptr[idx]; return p_stor.first()[idx];
} }
explicit operator bool() const { explicit operator bool() const {
return p_stor.p_ptr != nullptr; return p_stor.first() != nullptr;
} }
Pointer get() const { return p_stor.p_ptr; } Pointer get() const { return p_stor.first(); }
Dref get_deleter() { return p_stor.get_deleter(); } Dref get_deleter() { return p_stor.second(); }
Dcref get_deleter() const { return p_stor.get_deleter(); } Dcref get_deleter() const { return p_stor.second(); }
Pointer release() { Pointer release() {
Pointer p = p_stor.p_ptr; Pointer p = p_stor.first();
p_stor.p_ptr = nullptr; p_stor.first() = nullptr;
return p; return p;
} }
template<typename U> EnableIf< template<typename U> EnableIf<
octa::detail::SameOrLessCvQualified<U, Pointer>::value, void octa::detail::SameOrLessCvQualified<U, Pointer>::value, void
> reset(U p) { > reset(U p) {
Pointer tmp = p_stor.p_ptr; Pointer tmp = p_stor.first();
p_stor.p_ptr = p; p_stor.first() = p;
if (tmp) p_stor.get_deleter()(tmp); if (tmp) p_stor.second()(tmp);
} }
void reset(octa::Nullptr) { void reset(octa::Nullptr) {
Pointer tmp = p_stor.p_ptr; Pointer tmp = p_stor.first();
p_stor.p_ptr = nullptr; p_stor.first() = nullptr;
if (tmp) p_stor.get_deleter()(tmp); if (tmp) p_stor.second()(tmp);
} }
void reset() { void reset() {
@ -517,7 +480,7 @@ public:
} }
private: private:
octa::detail::BoxPair<T, D> p_stor; octa::detail::CompressedPair<T *, D> p_stor;
}; };
namespace detail { namespace detail {

View File

@ -133,7 +133,7 @@ private:
template<typename T, typename A> template<typename T, typename A>
class StringBase { class StringBase {
octa::Vector<T> p_buf; octa::Vector<T, A> p_buf;
void terminate() { void terminate() {
if (p_buf.empty() || (p_buf.back() != '\0')) p_buf.push('\0'); if (p_buf.empty() || (p_buf.back() != '\0')) p_buf.push('\0');
@ -417,7 +417,7 @@ namespace detail {
n = 0; n = 0;
*(s->data()) = '\0'; *(s->data()) = '\0';
} }
*(((octa::Size *)s) + 1) = n + 1; *((octa::Size *)s) = n + 1;
} }
} }

View File

@ -166,6 +166,125 @@ Pair<typename octa::detail::MakePairRet<T>::Type,
>(forward<T>(a), forward<U>(b));; >(forward<T>(a), forward<U>(b));;
} }
namespace detail {
template<typename T, typename U,
bool = octa::IsSame<octa::RemoveCv<T>, octa::RemoveCv<U>>::value,
bool = octa::IsEmpty<T>::value,
bool = octa::IsEmpty<U>::value
> struct CompressedPairSwitch;
/* neither empty */
template<typename T, typename U, bool Same>
struct CompressedPairSwitch<T, U, Same, false, false> { enum { value = 0 }; };
/* first empty */
template<typename T, typename U, bool Same>
struct CompressedPairSwitch<T, U, Same, true, false> { enum { value = 1 }; };
/* second empty */
template<typename T, typename U, bool Same>
struct CompressedPairSwitch<T, U, Same, false, true> { enum { value = 2 }; };
/* both empty, not the same */
template<typename T, typename U>
struct CompressedPairSwitch<T, U, false, true, true> { enum { value = 3 }; };
/* both empty and same */
template<typename T, typename U>
struct CompressedPairSwitch<T, U, true, true, true> { enum { value = 1 }; };
template<typename T, typename U, octa::Size = CompressedPairSwitch<T, U>::value>
struct CompressedPairBase;
template<typename T, typename U>
struct CompressedPairBase<T, U, 0> {
T p_first;
U p_second;
CompressedPairBase(T a, U b): p_first(octa::forward<T>(a)),
p_second(octa::forward<U>(b)) {}
T &first() { return p_first; }
const T &first() const { return p_first; }
U &second() { return p_second; }
const U &second() const { return p_second; }
void swap(CompressedPairBase &v) {
octa::swap(p_first, v.p_first);
octa::swap(p_second, v.p_second);
}
};
template<typename T, typename U>
struct CompressedPairBase<T, U, 1>: T {
U p_second;
CompressedPairBase(T a, U b): T(octa::forward<T>(a)),
p_second(octa::forward<U>(b)) {}
T &first() { return *this; }
const T &first() const { return *this; }
U &second() { return p_second; }
const U &second() const { return p_second; }
void swap(CompressedPairBase &v) {
octa::swap(p_second, v.p_second);
}
};
template<typename T, typename U>
struct CompressedPairBase<T, U, 2>: U {
T p_first;
CompressedPairBase(T a, U b): U(octa::forward<U>(b)),
p_first(octa::forward<T>(a)) {}
T &first() { return p_first; }
const T &first() const { return p_first; }
U &second() { return *this; }
const U &second() const { return *this; }
void swap(CompressedPairBase &v) {
octa::swap(p_first, v.p_first);
}
};
template<typename T, typename U>
struct CompressedPairBase<T, U, 3>: T, U {
CompressedPairBase(T a, U b): T(octa::forward<T>(a)),
U(octa::forward<U>(b)) {}
T &first() { return *this; }
const T &first() const { return *this; }
U &second() { return *this; }
const U &second() const { return *this; }
void swap(CompressedPairBase &) {}
};
template<typename T, typename U>
struct CompressedPair: CompressedPairBase<T, U> {
typedef CompressedPairBase<T, U> Base;
CompressedPair(T a, U b): Base(octa::forward<T>(a),
octa::forward<U>(b)) {}
T &first() { return Base::first(); }
const T &first() const { return Base::first(); }
U &second() { return Base::second(); }
const U &second() const { return Base::second(); }
void swap(CompressedPair &v) {
Base::swap(v);
}
};
} /* namespace detail */
} /* namespace octa */ } /* namespace octa */
#endif #endif

View File

@ -19,56 +19,20 @@
namespace octa { namespace octa {
namespace detail { namespace detail {
template<typename A, bool = octa::IsEmpty<A>::value>
struct VectorPair;
template<typename A>
struct VectorPair<A, false> { /* non-empty allocator */
octa::AllocatorPointer<A> p_ptr;
A p_a;
template<typename U>
VectorPair(octa::AllocatorPointer<A> ptr, U &&a): p_ptr(ptr),
p_a(octa::forward<U>(a)) {}
A &get_alloc() { return p_a; }
const A &get_alloc() const { return p_a; }
void swap(VectorPair &v) {
octa::swap(p_ptr, v.p_ptr);
octa::swap(p_a , v.p_a );
}
};
template<typename A>
struct VectorPair<A, true>: A { /* empty allocator */
octa::AllocatorPointer<A> p_ptr;
template<typename U>
VectorPair(octa::AllocatorPointer<A> ptr, U &&a):
A(octa::forward<U>(a)), p_ptr(ptr) {}
A &get_alloc() { return *this; }
const A &get_alloc() const { return *this; }
void swap(VectorPair &v) {
octa::swap(p_ptr, v.p_ptr);
}
};
} /* namespace detail */ } /* namespace detail */
template<typename T, typename A = octa::Allocator<T>> template<typename T, typename A = octa::Allocator<T>>
class Vector { class Vector {
using VecPair = octa::detail::VectorPair<A>; using VecPair = octa::detail::CompressedPair<octa::AllocatorPointer<A>, A>;
VecPair p_buf;
octa::Size p_len, p_cap; octa::Size p_len, p_cap;
VecPair p_buf;
void insert_base(octa::Size idx, octa::Size n) { void insert_base(octa::Size idx, octa::Size n) {
if (p_len + n > p_cap) reserve(p_len + n); if (p_len + n > p_cap) reserve(p_len + n);
p_len += n; p_len += n;
for (octa::Size i = p_len - 1; i > idx + n - 1; --i) { for (octa::Size i = p_len - 1; i > idx + n - 1; --i) {
p_buf.p_ptr[i] = octa::move(p_buf.p_ptr[i - n]); p_buf.first()[i] = octa::move(p_buf.first()[i - n]);
} }
} }
@ -80,12 +44,12 @@ class Vector {
reserve(l); reserve(l);
p_len = l; p_len = l;
if (octa::IsPod<T>() && octa::IsSame<T, octa::RangeValue<R>>()) { if (octa::IsPod<T>() && octa::IsSame<T, octa::RangeValue<R>>()) {
memcpy(p_buf.p_ptr, &range.front(), range.size()); memcpy(p_buf.first(), &range.front(), range.size());
return; return;
} }
for (octa::Size i = 0; !range.empty(); range.pop_front()) { for (octa::Size i = 0; !range.empty(); range.pop_front()) {
octa::allocator_construct(p_buf.get_alloc(), octa::allocator_construct(p_buf.second(),
&p_buf.p_ptr[i], range.front()); &p_buf.first()[i], range.front());
++i; ++i;
} }
} }
@ -97,8 +61,8 @@ class Vector {
octa::Size i = 0; octa::Size i = 0;
for (; !range.empty(); range.pop_front()) { for (; !range.empty(); range.pop_front()) {
reserve(i + 1); reserve(i + 1);
octa::allocator_construct(p_buf.get_alloc(), octa::allocator_construct(p_buf.second(),
&p_buf.p_ptr[i], range.front()); &p_buf.first()[i], range.front());
++i; ++i;
p_len = i; p_len = i;
} }
@ -106,12 +70,12 @@ class Vector {
void copy_contents(const Vector &v) { void copy_contents(const Vector &v) {
if (octa::IsPod<T>()) { if (octa::IsPod<T>()) {
memcpy(p_buf.p_ptr, v.p_buf.p_ptr, p_len * sizeof(T)); memcpy(p_buf.first(), v.p_buf.first(), p_len * sizeof(T));
} else { } else {
Pointer cur = p_buf.p_ptr, last = p_buf.p_ptr + p_len; Pointer cur = p_buf.first(), last = p_buf.first() + p_len;
Pointer vbuf = v.p_buf.p_ptr; Pointer vbuf = v.p_buf.first();
while (cur != last) { while (cur != last) {
octa::allocator_construct(p_buf.get_alloc(), octa::allocator_construct(p_buf.second(),
cur++, *vbuf++); cur++, *vbuf++);
} }
} }
@ -133,71 +97,69 @@ public:
>; >;
using Allocator = A; using Allocator = A;
Vector(const A &a = A()): p_buf(nullptr, a), p_len(0), p_cap(0) {} Vector(const A &a = A()): p_len(0), p_cap(0), p_buf(nullptr, a) {}
explicit Vector(Size n, const T &val = T(), explicit Vector(Size n, const T &val = T(),
const A &al = A()): Vector(al) { const A &al = A()): Vector(al) {
p_buf.p_ptr = octa::allocator_allocate(p_buf.get_alloc(), n); p_buf.first() = octa::allocator_allocate(p_buf.second(), n);
p_len = p_cap = n; p_len = p_cap = n;
Pointer cur = p_buf.p_ptr, last = p_buf.p_ptr + n; Pointer cur = p_buf.first(), last = p_buf.first() + n;
while (cur != last) while (cur != last)
octa::allocator_construct(p_buf.get_alloc(), cur++, val); octa::allocator_construct(p_buf.second(), cur++, val);
} }
Vector(const Vector &v): p_buf(nullptr, Vector(const Vector &v): p_len(0), p_cap(0), p_buf(nullptr,
octa::allocator_container_copy(v.p_buf.get_alloc())), p_len(0), octa::allocator_container_copy(v.p_buf.second())) {
p_cap(0) {
reserve(v.p_cap); reserve(v.p_cap);
p_len = v.p_len; p_len = v.p_len;
copy_contents(v); copy_contents(v);
} }
Vector(const Vector &v, const A &a): p_buf(nullptr, a), Vector(const Vector &v, const A &a): p_len(0), p_cap(0), p_buf(nullptr, a) {
p_len(0), p_cap(0) {
reserve(v.p_cap); reserve(v.p_cap);
p_len = v.p_len; p_len = v.p_len;
copy_contents(v); copy_contents(v);
} }
Vector(Vector &&v): p_buf(v.p_buf.p_ptr, Vector(Vector &&v): p_len(v.p_len), p_cap(v.p_cap), p_buf(v.p_buf.first(),
octa::move(v.p_buf.get_alloc())), p_len(v.p_len), p_cap(v.p_cap) { octa::move(v.p_buf.second())) {
v.p_buf.p_ptr = nullptr; v.p_buf.first() = nullptr;
v.p_len = v.p_cap = 0; v.p_len = v.p_cap = 0;
} }
Vector(Vector &&v, const A &a) { Vector(Vector &&v, const A &a) {
if (a != v.a) { if (a != v.a) {
p_buf.get_alloc() = a; p_buf.second() = a;
reserve(v.p_cap); reserve(v.p_cap);
p_len = v.p_len; p_len = v.p_len;
if (octa::IsPod<T>()) { if (octa::IsPod<T>()) {
memcpy(p_buf.p_ptr, v.p_buf.p_ptr, p_len * sizeof(T)); memcpy(p_buf.first(), v.p_buf.first(), p_len * sizeof(T));
} else { } else {
Pointer cur = p_buf.p_ptr, last = p_buf.p_ptr + p_len; Pointer cur = p_buf.first(), last = p_buf.first() + p_len;
Pointer vbuf = v.p_buf.p_ptr; Pointer vbuf = v.p_buf.first();
while (cur != last) { while (cur != last) {
octa::allocator_construct(p_buf.get_alloc(), cur++, octa::allocator_construct(p_buf.second(), cur++,
octa::move(*vbuf++)); octa::move(*vbuf++));
} }
} }
return; return;
} }
new (&p_buf) VecPair(v.p_buf.p_ptr, new (&p_buf) VecPair(v.p_buf.first(),
octa::move(v.p_buf.get_alloc())); octa::move(v.p_buf.second()));
p_len = v.p_len; p_len = v.p_len;
p_cap = v.p_cap; p_cap = v.p_cap;
v.p_buf.p_ptr = nullptr; v.p_buf.first() = nullptr;
v.p_len = v.p_cap = 0; v.p_len = v.p_cap = 0;
} }
Vector(ConstPointer buf, Size n, const A &a = A()): Vector(a) { Vector(ConstPointer buf, Size n, const A &a = A()): Vector(a) {
reserve(n); reserve(n);
if (octa::IsPod<T>()) { if (octa::IsPod<T>()) {
memcpy(p_buf.p_ptr, buf, n * sizeof(T)); memcpy(p_buf.first(), buf, n * sizeof(T));
} else { } else {
for (Size i = 0; i < n; ++i) for (Size i = 0; i < n; ++i)
octa::allocator_construct(p_buf.get_alloc(), octa::allocator_construct(p_buf.second(),
&p_buf.p_ptr[i], buf[i]); &p_buf.first()[i], buf[i]);
} }
p_len = n; p_len = n;
} }
@ -212,14 +174,14 @@ public:
~Vector() { ~Vector() {
clear(); clear();
octa::allocator_deallocate(p_buf.get_alloc(), p_buf.p_ptr, p_cap); octa::allocator_deallocate(p_buf.second(), p_buf.first(), p_cap);
} }
void clear() { void clear() {
if (p_len > 0 && !octa::IsPod<T>()) { if (p_len > 0 && !octa::IsPod<T>()) {
Pointer cur = p_buf.p_ptr, last = p_buf.p_ptr + p_len; Pointer cur = p_buf.first(), last = p_buf.first() + p_len;
while (cur != last) while (cur != last)
octa::allocator_destroy(p_buf.get_alloc(), cur++); octa::allocator_destroy(p_buf.second(), cur++);
} }
p_len = 0; p_len = 0;
} }
@ -235,11 +197,11 @@ public:
Vector &operator=(Vector &&v) { Vector &operator=(Vector &&v) {
clear(); clear();
octa::allocator_deallocate(p_buf.get_alloc(), p_buf.p_ptr, p_cap); octa::allocator_deallocate(p_buf.second(), p_buf.first(), p_cap);
p_len = v.p_len; p_len = v.p_len;
p_cap = v.p_cap; p_cap = v.p_cap;
p_buf.~VecPair(); p_buf.~VecPair();
new (&p_buf) VecPair(v.disown(), octa::move(v.p_buf.get_alloc())); new (&p_buf) VecPair(v.disown(), octa::move(v.p_buf.second()));
return *this; return *this;
} }
@ -248,12 +210,12 @@ public:
Size ilen = il.end() - il.begin(); Size ilen = il.end() - il.begin();
reserve(ilen); reserve(ilen);
if (octa::IsPod<T>()) { if (octa::IsPod<T>()) {
memcpy(p_buf.p_ptr, il.begin(), ilen); memcpy(p_buf.first(), il.begin(), ilen);
} else { } else {
Pointer tbuf = p_buf.p_ptr, ibuf = il.begin(), Pointer tbuf = p_buf.first(), ibuf = il.begin(),
last = il.end(); last = il.end();
while (ibuf != last) { while (ibuf != last) {
octa::allocator_construct(p_buf.get_alloc(), octa::allocator_construct(p_buf.second(),
tbuf++, *ibuf++); tbuf++, *ibuf++);
} }
} }
@ -274,13 +236,13 @@ public:
p_len = n; p_len = n;
if (octa::IsPod<T>()) { if (octa::IsPod<T>()) {
for (Size i = l; i < p_len; ++i) { for (Size i = l; i < p_len; ++i) {
p_buf.p_ptr[i] = T(v); p_buf.first()[i] = T(v);
} }
} else { } else {
Pointer first = p_buf.p_ptr + l; Pointer first = p_buf.first() + l;
Pointer last = p_buf.p_ptr + p_len; Pointer last = p_buf.first() + p_len;
while (first != last) while (first != last)
octa::allocator_construct(p_buf.get_alloc(), first++, v); octa::allocator_construct(p_buf.second(), first++, v);
} }
} }
@ -292,69 +254,69 @@ public:
} else { } else {
while (p_cap < n) p_cap *= 2; while (p_cap < n) p_cap *= 2;
} }
Pointer tmp = octa::allocator_allocate(p_buf.get_alloc(), p_cap); Pointer tmp = octa::allocator_allocate(p_buf.second(), p_cap);
if (oc > 0) { if (oc > 0) {
if (octa::IsPod<T>()) { if (octa::IsPod<T>()) {
memcpy(tmp, p_buf.p_ptr, p_len * sizeof(T)); memcpy(tmp, p_buf.first(), p_len * sizeof(T));
} else { } else {
Pointer cur = p_buf.p_ptr, tcur = tmp, Pointer cur = p_buf.first(), tcur = tmp,
last = tmp + p_len; last = tmp + p_len;
while (tcur != last) { while (tcur != last) {
octa::allocator_construct(p_buf.get_alloc(), tcur++, octa::allocator_construct(p_buf.second(), tcur++,
octa::move(*cur)); octa::move(*cur));
octa::allocator_destroy(p_buf.get_alloc(), cur); octa::allocator_destroy(p_buf.second(), cur);
++cur; ++cur;
} }
} }
octa::allocator_deallocate(p_buf.get_alloc(), p_buf.p_ptr, oc); octa::allocator_deallocate(p_buf.second(), p_buf.first(), oc);
} }
p_buf.p_ptr = tmp; p_buf.first() = tmp;
} }
T &operator[](Size i) { return p_buf.p_ptr[i]; } T &operator[](Size i) { return p_buf.first()[i]; }
const T &operator[](Size i) const { return p_buf.p_ptr[i]; } const T &operator[](Size i) const { return p_buf.first()[i]; }
T &at(Size i) { return p_buf.p_ptr[i]; } T &at(Size i) { return p_buf.first()[i]; }
const T &at(Size i) const { return p_buf.p_ptr[i]; } const T &at(Size i) const { return p_buf.first()[i]; }
T &push(const T &v) { T &push(const T &v) {
if (p_len == p_cap) reserve(p_len + 1); if (p_len == p_cap) reserve(p_len + 1);
octa::allocator_construct(p_buf.get_alloc(), octa::allocator_construct(p_buf.second(),
&p_buf.p_ptr[p_len], v); &p_buf.first()[p_len], v);
return p_buf.p_ptr[p_len++]; return p_buf.first()[p_len++];
} }
T &push() { T &push() {
if (p_len == p_cap) reserve(p_len + 1); if (p_len == p_cap) reserve(p_len + 1);
octa::allocator_construct(p_buf.get_alloc(), &p_buf.p_ptr[p_len]); octa::allocator_construct(p_buf.second(), &p_buf.first()[p_len]);
return p_buf.p_ptr[p_len++]; return p_buf.first()[p_len++];
} }
template<typename ...U> template<typename ...U>
T &emplace_back(U &&...args) { T &emplace_back(U &&...args) {
if (p_len == p_cap) reserve(p_len + 1); if (p_len == p_cap) reserve(p_len + 1);
octa::allocator_construct(p_buf.get_alloc(), &p_buf.p_ptr[p_len], octa::allocator_construct(p_buf.second(), &p_buf.first()[p_len],
octa::forward<U>(args)...); octa::forward<U>(args)...);
return p_buf.p_ptr[p_len++]; return p_buf.first()[p_len++];
} }
void pop() { void pop() {
if (!octa::IsPod<T>()) { if (!octa::IsPod<T>()) {
octa::allocator_destroy(p_buf.get_alloc(), octa::allocator_destroy(p_buf.second(),
&p_buf.p_ptr[--p_len]); &p_buf.first()[--p_len]);
} else { } else {
--p_len; --p_len;
} }
} }
T &front() { return p_buf.p_ptr[0]; } T &front() { return p_buf.first()[0]; }
const T &front() const { return p_buf.p_ptr[0]; } const T &front() const { return p_buf.first()[0]; }
T &back() { return p_buf.p_ptr[p_len - 1]; } T &back() { return p_buf.first()[p_len - 1]; }
const T &back() const { return p_buf.p_ptr[p_len - 1]; } const T &back() const { return p_buf.first()[p_len - 1]; }
Pointer data() { return p_buf.p_ptr; } Pointer data() { return p_buf.first(); }
ConstPointer data() const { return p_buf.p_ptr; } ConstPointer data() const { return p_buf.first(); }
Size size() const { return p_len; } Size size() const { return p_len; }
Size capacity() const { return p_cap; } Size capacity() const { return p_cap; }
@ -364,34 +326,34 @@ public:
bool in_range(Size idx) { return idx < p_len; } bool in_range(Size idx) { return idx < p_len; }
bool in_range(int idx) { return idx >= 0 && Size(idx) < p_len; } bool in_range(int idx) { return idx >= 0 && Size(idx) < p_len; }
bool in_range(ConstPointer ptr) { bool in_range(ConstPointer ptr) {
return ptr >= p_buf.p_ptr && ptr < &p_buf.p_ptr[p_len]; return ptr >= p_buf.first() && ptr < &p_buf.first()[p_len];
} }
Pointer disown() { Pointer disown() {
Pointer r = p_buf.p_ptr; Pointer r = p_buf.first();
p_buf.p_ptr = nullptr; p_buf.first() = nullptr;
p_len = p_cap = 0; p_len = p_cap = 0;
return r; return r;
} }
Range insert(Size idx, T &&v) { Range insert(Size idx, T &&v) {
insert_base(idx, 1); insert_base(idx, 1);
p_buf.p_ptr[idx] = octa::move(v); p_buf.first()[idx] = octa::move(v);
return Range(&p_buf.p_ptr[idx], &p_buf.p_ptr[p_len]); return Range(&p_buf.first()[idx], &p_buf.first()[p_len]);
} }
Range insert(Size idx, const T &v) { Range insert(Size idx, const T &v) {
insert_base(idx, 1); insert_base(idx, 1);
p_buf.p_ptr[idx] = v; p_buf.first()[idx] = v;
return Range(&p_buf.p_ptr[idx], &p_buf.p_ptr[p_len]); return Range(&p_buf.first()[idx], &p_buf.first()[p_len]);
} }
Range insert(Size idx, Size n, const T &v) { Range insert(Size idx, Size n, const T &v) {
insert_base(idx, n); insert_base(idx, n);
for (Size i = 0; i < n; ++i) { for (Size i = 0; i < n; ++i) {
p_buf.p_ptr[idx + i] = v; p_buf.first()[idx + i] = v;
} }
return Range(&p_buf.p_ptr[idx], &p_buf.p_ptr[p_len]); return Range(&p_buf.first()[idx], &p_buf.first()[p_len]);
} }
template<typename U> template<typename U>
@ -399,10 +361,10 @@ public:
Size l = range.size(); Size l = range.size();
insert_base(idx, l); insert_base(idx, l);
for (Size i = 0; i < l; ++i) { for (Size i = 0; i < l; ++i) {
p_buf.p_ptr[idx + i] = range.front(); p_buf.first()[idx + i] = range.front();
range.pop_front(); range.pop_front();
} }
return Range(&p_buf.p_ptr[idx], &p_buf.p_ptr[p_len]); return Range(&p_buf.first()[idx], &p_buf.first()[p_len]);
} }
Range insert(Size idx, InitializerList<T> il) { Range insert(Size idx, InitializerList<T> il) {
@ -410,13 +372,13 @@ public:
} }
Range each() { Range each() {
return Range(p_buf.p_ptr, p_buf.p_ptr + p_len); return Range(p_buf.first(), p_buf.first() + p_len);
} }
ConstRange each() const { ConstRange each() const {
return ConstRange(p_buf.p_ptr, p_buf.p_ptr + p_len); return ConstRange(p_buf.first(), p_buf.first() + p_len);
} }
ConstRange ceach() const { ConstRange ceach() const {
return ConstRange(p_buf.p_ptr, p_buf.p_ptr + p_len); return ConstRange(p_buf.first(), p_buf.first() + p_len);
} }
void swap(Vector &v) { void swap(Vector &v) {
@ -426,7 +388,7 @@ public:
} }
A get_allocator() const { A get_allocator() const {
return p_buf.get_alloc(); return p_buf.second();
} }
}; };