remove the noexcept stuff; nothing in octastd ever throws

master
Daniel Kolesa 2015-05-20 22:05:41 +01:00
parent 25fb30b524
commit 64810e4006
9 changed files with 452 additions and 804 deletions

View File

@ -23,39 +23,39 @@ namespace octa {
typedef PointerRange< T> RangeType; typedef PointerRange< T> RangeType;
typedef PointerRange<const T> ConstRangeType; typedef PointerRange<const T> ConstRangeType;
T &operator[](size_t i) noexcept { return p_buf[i]; } T &operator[](size_t i) { return p_buf[i]; }
const T &operator[](size_t i) const noexcept { return p_buf[i]; } const T &operator[](size_t i) const { return p_buf[i]; }
T &at(size_t i) noexcept { return p_buf[i]; } T &at(size_t i) { return p_buf[i]; }
const T &at(size_t i) const noexcept { return p_buf[i]; } const T &at(size_t i) const { return p_buf[i]; }
T &first() noexcept { return p_buf[0]; } T &first() { return p_buf[0]; }
const T &first() const noexcept { return p_buf[0]; } const T &first() const { return p_buf[0]; }
T &last() noexcept { return p_buf[N - 1]; } T &last() { return p_buf[N - 1]; }
const T &last() const noexcept { return p_buf[N - 1]; } const T &last() const { return p_buf[N - 1]; }
size_t length() const noexcept { return N; } size_t length() const { return N; }
bool empty() const noexcept { return N == 0; } bool empty() const { return N == 0; }
bool in_range(size_t idx) noexcept { return idx < N; } bool in_range(size_t idx) { return idx < N; }
bool in_range(int idx) noexcept { return idx >= 0 && idx < N; } bool in_range(int idx) { return idx >= 0 && idx < N; }
bool in_range(const T *ptr) noexcept { bool in_range(const T *ptr) {
return ptr >= &p_buf[0] && ptr < &p_buf[N]; return ptr >= &p_buf[0] && ptr < &p_buf[N];
} }
T *get() noexcept { return p_buf; } T *get() { return p_buf; }
const T *get() const noexcept { return p_buf; } const T *get() const { return p_buf; }
void swap(Array &v) noexcept(swap(declval<T &>(), declval<T &>())) { void swap(Array &v)(swap(declval<T &>(), declval<T &>())) {
swap(p_buf, v.p_buf); swap(p_buf, v.p_buf);
} }
RangeType each() noexcept { RangeType each() {
return PointerRange<T>(p_buf, p_buf + N); return PointerRange<T>(p_buf, p_buf + N);
} }
ConstRangeType each() const noexcept { ConstRangeType each() const {
return PointerRange<const T>(p_buf, p_buf + N); return PointerRange<const T>(p_buf, p_buf + N);
} }
@ -63,7 +63,7 @@ namespace octa {
}; };
template<typename T, size_t N> template<typename T, size_t N>
void swap(Array<T, N> &a, Array<T, N> &b) noexcept(noexcept(a.swap(b))) { void swap(Array<T, N> &a, Array<T, N> &b) {
a.swap(b); a.swap(b);
} }
} }

View File

@ -24,8 +24,8 @@ namespace octa {
template<typename T> template<typename T>
struct __OctaAtomicBase { struct __OctaAtomicBase {
__OctaAtomicBase() noexcept {} __OctaAtomicBase() {}
explicit __OctaAtomicBase(T v) noexcept: value(v) {} explicit __OctaAtomicBase(T v): value(v) {}
T value; T value;
}; };
@ -112,8 +112,7 @@ namespace octa {
template<typename T> template<typename T>
struct __OctaMsvcAtomicStore<T, 1> { struct __OctaMsvcAtomicStore<T, 1> {
static inline void store(volatile T *dst, T src, MemoryOrder ord) static inline void store(volatile T *dst, T src, MemoryOrder ord) {
noexcept {
if (ord == MemoryOrder::seq_cst) if (ord == MemoryOrder::seq_cst)
InterlockedExchange8((volatile int8_t *)dst, (int8_t)src); InterlockedExchange8((volatile int8_t *)dst, (int8_t)src);
else *dst = src; else *dst = src;
@ -122,8 +121,7 @@ namespace octa {
template<typename T> template<typename T>
struct __OctaMsvcAtomicStore<T, 2> { struct __OctaMsvcAtomicStore<T, 2> {
static inline void store(volatile T *dst, T src, MemoryOrder ord) static inline void store(volatile T *dst, T src, MemoryOrder ord) {
noexcept {
if (ord == MemoryOrder::seq_cst) if (ord == MemoryOrder::seq_cst)
InterlockedExchange16((volatile int16_t *)dst, (int16_t)src); InterlockedExchange16((volatile int16_t *)dst, (int16_t)src);
else *dst = src; else *dst = src;
@ -132,8 +130,7 @@ namespace octa {
template<typename T> template<typename T>
struct __OctaMsvcAtomicStore<T, 4> { struct __OctaMsvcAtomicStore<T, 4> {
static inline void store(volatile T *dst, T src, MemoryOrder ord) static inline void store(volatile T *dst, T src, MemoryOrder ord) {
noexcept {
if (ord == MemoryOrder::seq_cst) if (ord == MemoryOrder::seq_cst)
InterlockedExchange((volatile int32_t *)dst, (int32_t)src); InterlockedExchange((volatile int32_t *)dst, (int32_t)src);
else *dst = src; else *dst = src;
@ -142,8 +139,7 @@ namespace octa {
template<typename T> template<typename T>
struct __OctaMsvcAtomicStore<T, 8> { struct __OctaMsvcAtomicStore<T, 8> {
static inline void store(volatile T *dst, T src, MemoryOrder ord) static inline void store(volatile T *dst, T src, MemoryOrder ord) {
noexcept {
if (ord == MemoryOrder::relaxed) if (ord == MemoryOrder::relaxed)
InterlockedExchangeNoFence64((volatile int64_t *)dst, (int64_t)src); InterlockedExchangeNoFence64((volatile int64_t *)dst, (int64_t)src);
else else
@ -168,26 +164,22 @@ namespace octa {
template<typename T> template<typename T>
struct __OctaMsvcAtomicLoad<T, 1> { struct __OctaMsvcAtomicLoad<T, 1> {
static inline void load(volatile T *src, T *dst) static inline void load(volatile T *src, T *dst) { *dst = *src; }
noexcept { *dst = *src; }
}; };
template<typename T> template<typename T>
struct __OctaMsvcAtomicLoad<T, 2> { struct __OctaMsvcAtomicLoad<T, 2> {
static inline void load(volatile T *src, T *dst) static inline void load(volatile T *src, T *dst) { *dst = *src; }
noexcept { *dst = *src; }
}; };
template<typename T> template<typename T>
struct __OctaMsvcAtomicLoad<T, 4> { struct __OctaMsvcAtomicLoad<T, 4> {
static inline void load(volatile T *src, T *dst) static inline void load(volatile T *src, T *dst) { *dst = *src; }
noexcept { *dst = *src; }
}; };
template<typename T> template<typename T>
struct __OctaMsvcAtomicLoad<T, 8> { struct __OctaMsvcAtomicLoad<T, 8> {
static inline void load(volatile T *src, T *dst) static inline void load(volatile T *src, T *dst) {
noexcept {
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4047) #pragma warning(disable:4047)
*dst = InterlockedOr64((volatile int64_t *)(src), 0); *dst = InterlockedOr64((volatile int64_t *)(src), 0);
@ -216,32 +208,28 @@ namespace octa {
template<typename T> template<typename T>
struct __OctaMsvcAtomicExchange<T, 1> { struct __OctaMsvcAtomicExchange<T, 1> {
static inline void exchange(volatile T *dst, T src, T *ret) static inline void exchange(volatile T *dst, T src, T *ret) {
noexcept {
*ret = InterlockedExchange8((volatile int8_t *)dst, (int8_t)src); *ret = InterlockedExchange8((volatile int8_t *)dst, (int8_t)src);
} }
}; };
template<typename T> template<typename T>
struct __OctaMsvcAtomicExchange<T, 2> { struct __OctaMsvcAtomicExchange<T, 2> {
static inline void exchange(volatile T *dst, T src, T *ret) static inline void exchange(volatile T *dst, T src, T *ret) {
noexcept {
*ret = InterlockedExchange16((volatile int16_t *)dst, (int16_t)src); *ret = InterlockedExchange16((volatile int16_t *)dst, (int16_t)src);
} }
}; };
template<typename T> template<typename T>
struct __OctaMsvcAtomicExchange<T, 4> { struct __OctaMsvcAtomicExchange<T, 4> {
static inline void exchange(volatile T *dst, T src, T *ret) static inline void exchange(volatile T *dst, T src, T *ret) {
noexcept {
*ret = InterlockedExchange((volatile int32_t *)dst, (int32_t)src); *ret = InterlockedExchange((volatile int32_t *)dst, (int32_t)src);
} }
}; };
template<typename T> template<typename T>
struct __OctaMsvcAtomicExchange<T, 8> { struct __OctaMsvcAtomicExchange<T, 8> {
static inline void exchange(volatile T *dst, T src, T *ret) static inline void exchange(volatile T *dst, T src, T *ret) {
noexcept {
*ret = InterlockedExchange64((volatile int64_t *)dst, (int64_t)src); *ret = InterlockedExchange64((volatile int64_t *)dst, (int64_t)src);
} }
}; };
@ -267,8 +255,7 @@ namespace octa {
template<typename T> template<typename T>
struct __OctaMsvcAtomicCompareExchange<T, 1> { struct __OctaMsvcAtomicCompareExchange<T, 1> {
static inline bool exchange(volatile T *dst, T *exp, T src) static inline bool exchange(volatile T *dst, T *exp, T src) {
noexcept {
int8_t prev = _InterlockedCompareExchange8((volatile int8_t *)dst, int8_t prev = _InterlockedCompareExchange8((volatile int8_t *)dst,
(int8_t)src, (int8_t)*exp); (int8_t)src, (int8_t)*exp);
if (prev == (int8_t)*exp) return true; if (prev == (int8_t)*exp) return true;
@ -278,8 +265,7 @@ namespace octa {
template<typename T> template<typename T>
struct __OctaMsvcAtomicCompareExchange<T, 2> { struct __OctaMsvcAtomicCompareExchange<T, 2> {
static inline bool exchange(volatile T *dst, T *exp, T src) static inline bool exchange(volatile T *dst, T *exp, T src) {
noexcept {
int16_t prev = _InterlockedCompareExchange16((volatile int16_t *)dst, int16_t prev = _InterlockedCompareExchange16((volatile int16_t *)dst,
(int16_t)src, (int16_t)*exp); (int16_t)src, (int16_t)*exp);
if (prev == (int16_t)*exp) return true; if (prev == (int16_t)*exp) return true;
@ -289,8 +275,7 @@ namespace octa {
template<typename T> template<typename T>
struct __OctaMsvcAtomicCompareExchange<T, 4> { struct __OctaMsvcAtomicCompareExchange<T, 4> {
static inline bool exchange(volatile T *dst, T *exp, T src) static inline bool exchange(volatile T *dst, T *exp, T src) {
noexcept {
int32_t prev = _InterlockedCompareExchange((volatile int32_t *)dst, int32_t prev = _InterlockedCompareExchange((volatile int32_t *)dst,
(int32_t)src, (int32_t)*exp); (int32_t)src, (int32_t)*exp);
if (prev == (int32_t)*exp) return true; if (prev == (int32_t)*exp) return true;
@ -300,8 +285,7 @@ namespace octa {
template<typename T> template<typename T>
struct __OctaMsvcAtomicCompareExchange<T, 8> { struct __OctaMsvcAtomicCompareExchange<T, 8> {
static inline bool exchange(volatile T *dst, T *exp, T src) static inline bool exchange(volatile T *dst, T *exp, T src) {
noexcept {
int64_t prev = _InterlockedCompareExchange64((volatile int64_t *)dst, int64_t prev = _InterlockedCompareExchange64((volatile int64_t *)dst,
(int64_t)src, (int64_t)*exp); (int64_t)src, (int64_t)*exp);
if (prev == (int64_t)*exp) return true; if (prev == (int64_t)*exp) return true;
@ -668,7 +652,7 @@ namespace octa {
#endif #endif
#endif #endif
template <typename T> inline T kill_dependency(T v) noexcept { template <typename T> inline T kill_dependency(T v) {
return v; return v;
} }
@ -676,93 +660,87 @@ namespace octa {
struct __OctaAtomic { struct __OctaAtomic {
mutable __OctaAtomicBase<T> p_a; mutable __OctaAtomicBase<T> p_a;
__OctaAtomic() noexcept = default; __OctaAtomic() = default;
constexpr __OctaAtomic(T v) noexcept: p_a(v) {} constexpr __OctaAtomic(T v): p_a(v) {}
__OctaAtomic(const __OctaAtomic &) = delete; __OctaAtomic(const __OctaAtomic &) = delete;
__OctaAtomic &operator=(const __OctaAtomic &) = delete; __OctaAtomic &operator=(const __OctaAtomic &) = delete;
__OctaAtomic &operator=(const __OctaAtomic &) volatile = delete; __OctaAtomic &operator=(const __OctaAtomic &) volatile = delete;
bool is_lock_free() const volatile noexcept { bool is_lock_free() const volatile {
return __octa_atomic_is_lock_free(sizeof(T)); return __octa_atomic_is_lock_free(sizeof(T));
} }
bool is_lock_free() const noexcept { bool is_lock_free() const {
return __octa_atomic_is_lock_free(sizeof(T)); return __octa_atomic_is_lock_free(sizeof(T));
} }
void store(T v, MemoryOrder ord = MemoryOrder::seq_cst) void store(T v, MemoryOrder ord = MemoryOrder::seq_cst) volatile {
volatile noexcept {
__octa_atomic_store(&p_a, v, ord); __octa_atomic_store(&p_a, v, ord);
} }
void store(T v, MemoryOrder ord = MemoryOrder::seq_cst) noexcept { void store(T v, MemoryOrder ord = MemoryOrder::seq_cst) {
__octa_atomic_store(&p_a, v, ord); __octa_atomic_store(&p_a, v, ord);
} }
T load(MemoryOrder ord = MemoryOrder::seq_cst) const volatile noexcept { T load(MemoryOrder ord = MemoryOrder::seq_cst) const volatile {
return __octa_atomic_load(&p_a, ord); return __octa_atomic_load(&p_a, ord);
} }
T load(MemoryOrder ord = MemoryOrder::seq_cst) const noexcept { T load(MemoryOrder ord = MemoryOrder::seq_cst) const {
return __octa_atomic_load(&p_a, ord); return __octa_atomic_load(&p_a, ord);
} }
operator T() const volatile noexcept { return load(); } operator T() const volatile { return load(); }
operator T() const noexcept { return load(); } operator T() const { return load(); }
T exchange(T v, MemoryOrder ord = MemoryOrder::seq_cst) T exchange(T v, MemoryOrder ord = MemoryOrder::seq_cst) volatile {
volatile noexcept {
return __octa_atomic_exchange(&p_a, v, ord); return __octa_atomic_exchange(&p_a, v, ord);
} }
T exchange(T v, MemoryOrder ord = MemoryOrder::seq_cst) noexcept { T exchange(T v, MemoryOrder ord = MemoryOrder::seq_cst) {
return __octa_atomic_exchange(&p_a, v, ord); return __octa_atomic_exchange(&p_a, v, ord);
} }
bool compare_exchange_weak(T &e, T v, MemoryOrder s, MemoryOrder f) bool compare_exchange_weak(T &e, T v, MemoryOrder s, MemoryOrder f)
volatile noexcept { volatile {
return __octa_atomic_compare_exchange_weak(&p_a, &e, v, s, f); return __octa_atomic_compare_exchange_weak(&p_a, &e, v, s, f);
} }
bool compare_exchange_weak(T& e, T v, MemoryOrder s, MemoryOrder f) bool compare_exchange_weak(T& e, T v, MemoryOrder s, MemoryOrder f) {
noexcept {
return __octa_atomic_compare_exchange_weak(&p_a, &e, v, s, f); return __octa_atomic_compare_exchange_weak(&p_a, &e, v, s, f);
} }
bool compare_exchange_strong(T& e, T v, MemoryOrder s, MemoryOrder f) bool compare_exchange_strong(T& e, T v, MemoryOrder s, MemoryOrder f)
volatile noexcept { volatile {
return __octa_atomic_compare_exchange_strong(&p_a, &e, v, s, f); return __octa_atomic_compare_exchange_strong(&p_a, &e, v, s, f);
} }
bool compare_exchange_strong(T& e, T v, MemoryOrder s, MemoryOrder f) bool compare_exchange_strong(T& e, T v, MemoryOrder s, MemoryOrder f) {
noexcept {
return __octa_atomic_compare_exchange_strong(&p_a, &e, v, s, f); return __octa_atomic_compare_exchange_strong(&p_a, &e, v, s, f);
} }
bool compare_exchange_weak(T& e, T v, MemoryOrder ord bool compare_exchange_weak(T& e, T v, MemoryOrder ord
= MemoryOrder::seq_cst) = MemoryOrder::seq_cst)
volatile noexcept { volatile {
return __octa_atomic_compare_exchange_weak(&p_a, &e, v, ord, ord); return __octa_atomic_compare_exchange_weak(&p_a, &e, v, ord, ord);
} }
bool compare_exchange_weak(T& e, T v, MemoryOrder ord bool compare_exchange_weak(T& e, T v, MemoryOrder ord
= MemoryOrder::seq_cst) = MemoryOrder::seq_cst) {
noexcept {
return __octa_atomic_compare_exchange_weak(&p_a, &e, v, ord, ord); return __octa_atomic_compare_exchange_weak(&p_a, &e, v, ord, ord);
} }
bool compare_exchange_strong(T& e, T v, MemoryOrder ord bool compare_exchange_strong(T& e, T v, MemoryOrder ord
= MemoryOrder::seq_cst) = MemoryOrder::seq_cst)
volatile noexcept { volatile {
return __octa_atomic_compare_exchange_strong(&p_a, &e, v, ord, ord); return __octa_atomic_compare_exchange_strong(&p_a, &e, v, ord, ord);
} }
bool compare_exchange_strong(T& e, T v, MemoryOrder ord bool compare_exchange_strong(T& e, T v, MemoryOrder ord
= MemoryOrder::seq_cst) = MemoryOrder::seq_cst) {
noexcept {
return __octa_atomic_compare_exchange_strong(&p_a, &e, v, ord, ord); return __octa_atomic_compare_exchange_strong(&p_a, &e, v, ord, ord);
} }
}; };
@ -771,89 +749,84 @@ namespace octa {
struct __OctaAtomic<T, true>: __OctaAtomic<T, false> { struct __OctaAtomic<T, true>: __OctaAtomic<T, false> {
typedef __OctaAtomic<T, false> base_t; typedef __OctaAtomic<T, false> base_t;
__OctaAtomic() noexcept = default; __OctaAtomic() = default;
constexpr __OctaAtomic(T v) noexcept: base_t(v) {} constexpr __OctaAtomic(T v): base_t(v) {}
T fetch_add(T op, MemoryOrder ord = MemoryOrder::seq_cst) T fetch_add(T op, MemoryOrder ord = MemoryOrder::seq_cst) volatile {
volatile noexcept {
return __octa_atomic_fetch_add(&this->p_a, op, ord); return __octa_atomic_fetch_add(&this->p_a, op, ord);
} }
T fetch_add(T op, MemoryOrder ord = MemoryOrder::seq_cst) noexcept { T fetch_add(T op, MemoryOrder ord = MemoryOrder::seq_cst) {
return __octa_atomic_fetch_add(&this->p_a, op, ord); return __octa_atomic_fetch_add(&this->p_a, op, ord);
} }
T fetch_sub(T op, MemoryOrder ord = MemoryOrder::seq_cst) T fetch_sub(T op, MemoryOrder ord = MemoryOrder::seq_cst) volatile {
volatile noexcept {
return __octa_atomic_fetch_sub(&this->p_a, op, ord); return __octa_atomic_fetch_sub(&this->p_a, op, ord);
} }
T fetch_sub(T op, MemoryOrder ord = MemoryOrder::seq_cst) noexcept { T fetch_sub(T op, MemoryOrder ord = MemoryOrder::seq_cst) {
return __octa_atomic_fetch_sub(&this->p_a, op, ord); return __octa_atomic_fetch_sub(&this->p_a, op, ord);
} }
T fetch_and(T op, MemoryOrder ord = MemoryOrder::seq_cst) T fetch_and(T op, MemoryOrder ord = MemoryOrder::seq_cst) volatile {
volatile noexcept {
return __octa_atomic_fetch_and(&this->p_a, op, ord); return __octa_atomic_fetch_and(&this->p_a, op, ord);
} }
T fetch_and(T op, MemoryOrder ord = MemoryOrder::seq_cst) noexcept { T fetch_and(T op, MemoryOrder ord = MemoryOrder::seq_cst) {
return __octa_atomic_fetch_and(&this->p_a, op, ord); return __octa_atomic_fetch_and(&this->p_a, op, ord);
} }
T fetch_or(T op, MemoryOrder ord = MemoryOrder::seq_cst) T fetch_or(T op, MemoryOrder ord = MemoryOrder::seq_cst) volatile {
volatile noexcept {
return __octa_atomic_fetch_or(&this->p_a, op, ord); return __octa_atomic_fetch_or(&this->p_a, op, ord);
} }
T fetch_or(T op, MemoryOrder ord = MemoryOrder::seq_cst) noexcept { T fetch_or(T op, MemoryOrder ord = MemoryOrder::seq_cst) {
return __octa_atomic_fetch_or(&this->p_a, op, ord); return __octa_atomic_fetch_or(&this->p_a, op, ord);
} }
T fetch_xor(T op, MemoryOrder ord = MemoryOrder::seq_cst) T fetch_xor(T op, MemoryOrder ord = MemoryOrder::seq_cst) volatile {
volatile noexcept {
return __octa_atomic_fetch_xor(&this->p_a, op, ord); return __octa_atomic_fetch_xor(&this->p_a, op, ord);
} }
T fetch_xor(T op, MemoryOrder ord = MemoryOrder::seq_cst) noexcept { T fetch_xor(T op, MemoryOrder ord = MemoryOrder::seq_cst) {
return __octa_atomic_fetch_xor(&this->p_a, op, ord); return __octa_atomic_fetch_xor(&this->p_a, op, ord);
} }
T operator++(int) volatile noexcept { return fetch_add(T(1)); } T operator++(int) volatile { return fetch_add(T(1)); }
T operator++(int) noexcept { return fetch_add(T(1)); } T operator++(int) { return fetch_add(T(1)); }
T operator--(int) volatile noexcept { return fetch_sub(T(1)); } T operator--(int) volatile { return fetch_sub(T(1)); }
T operator--(int) noexcept { return fetch_sub(T(1)); } T operator--(int) { return fetch_sub(T(1)); }
T operator++( ) volatile noexcept { return fetch_add(T(1)) + T(1); } T operator++( ) volatile { return fetch_add(T(1)) + T(1); }
T operator++( ) noexcept { return fetch_add(T(1)) + T(1); } T operator++( ) { return fetch_add(T(1)) + T(1); }
T operator--( ) volatile noexcept { return fetch_sub(T(1)) - T(1); } T operator--( ) volatile { return fetch_sub(T(1)) - T(1); }
T operator--( ) noexcept { return fetch_sub(T(1)) - T(1); } T operator--( ) { return fetch_sub(T(1)) - T(1); }
T operator+=(T op) volatile noexcept { return fetch_add(op) + op; } T operator+=(T op) volatile { return fetch_add(op) + op; }
T operator+=(T op) noexcept { return fetch_add(op) + op; } T operator+=(T op) { return fetch_add(op) + op; }
T operator-=(T op) volatile noexcept { return fetch_sub(op) - op; } T operator-=(T op) volatile { return fetch_sub(op) - op; }
T operator-=(T op) noexcept { return fetch_sub(op) - op; } T operator-=(T op) { return fetch_sub(op) - op; }
T operator&=(T op) volatile noexcept { return fetch_and(op) & op; } T operator&=(T op) volatile { return fetch_and(op) & op; }
T operator&=(T op) noexcept { return fetch_and(op) & op; } T operator&=(T op) { return fetch_and(op) & op; }
T operator|=(T op) volatile noexcept { return fetch_or (op) | op; } T operator|=(T op) volatile { return fetch_or (op) | op; }
T operator|=(T op) noexcept { return fetch_or (op) | op; } T operator|=(T op) { return fetch_or (op) | op; }
T operator^=(T op) volatile noexcept { return fetch_xor(op) ^ op; } T operator^=(T op) volatile { return fetch_xor(op) ^ op; }
T operator^=(T op) noexcept { return fetch_xor(op) ^ op; } T operator^=(T op) { return fetch_xor(op) ^ op; }
}; };
template<typename T> template<typename T>
struct Atomic: __OctaAtomic<T> { struct Atomic: __OctaAtomic<T> {
typedef __OctaAtomic<T> base_t; typedef __OctaAtomic<T> base_t;
Atomic() noexcept = default; Atomic() = default;
constexpr Atomic(T v) noexcept: base_t(v) {} constexpr Atomic(T v): base_t(v) {}
T operator=(T v) volatile noexcept { T operator=(T v) volatile {
base_t::store(v); return v; base_t::store(v); return v;
} }
T operator=(T v) noexcept { T operator=(T v) {
base_t::store(v); return v; base_t::store(v); return v;
} }
}; };
@ -862,163 +835,152 @@ namespace octa {
struct Atomic<T *>: __OctaAtomic<T *> { struct Atomic<T *>: __OctaAtomic<T *> {
typedef __OctaAtomic<T *> base_t; typedef __OctaAtomic<T *> base_t;
Atomic() noexcept = default; Atomic() = default;
constexpr Atomic(T *v) noexcept: base_t(v) {} constexpr Atomic(T *v): base_t(v) {}
T *operator=(T *v) volatile noexcept { T *operator=(T *v) volatile {
base_t::store(v); return v; base_t::store(v); return v;
} }
T *operator=(T *v) noexcept { T *operator=(T *v) {
base_t::store(v); return v; base_t::store(v); return v;
} }
T *fetch_add(ptrdiff_t op, MemoryOrder ord = MemoryOrder::seq_cst) T *fetch_add(ptrdiff_t op, MemoryOrder ord = MemoryOrder::seq_cst)
volatile noexcept { volatile {
return __octa_atomic_fetch_add(&this->p_a, op, ord); return __octa_atomic_fetch_add(&this->p_a, op, ord);
} }
T *fetch_add(ptrdiff_t op, MemoryOrder ord = MemoryOrder::seq_cst) T *fetch_add(ptrdiff_t op, MemoryOrder ord = MemoryOrder::seq_cst) {
noexcept {
return __octa_atomic_fetch_add(&this->p_a, op, ord); return __octa_atomic_fetch_add(&this->p_a, op, ord);
} }
T *fetch_sub(ptrdiff_t op, MemoryOrder ord = MemoryOrder::seq_cst) T *fetch_sub(ptrdiff_t op, MemoryOrder ord = MemoryOrder::seq_cst)
volatile noexcept { volatile {
return __octa_atomic_fetch_sub(&this->p_a, op, ord); return __octa_atomic_fetch_sub(&this->p_a, op, ord);
} }
T *fetch_sub(ptrdiff_t op, MemoryOrder ord = MemoryOrder::seq_cst) T *fetch_sub(ptrdiff_t op, MemoryOrder ord = MemoryOrder::seq_cst) {
noexcept {
return __octa_atomic_fetch_sub(&this->p_a, op, ord); return __octa_atomic_fetch_sub(&this->p_a, op, ord);
} }
T *operator++(int) volatile noexcept { return fetch_add(1); } T *operator++(int) volatile { return fetch_add(1); }
T *operator++(int) noexcept { return fetch_add(1); } T *operator++(int) { return fetch_add(1); }
T *operator--(int) volatile noexcept { return fetch_sub(1); } T *operator--(int) volatile { return fetch_sub(1); }
T *operator--(int) noexcept { return fetch_sub(1); } T *operator--(int) { return fetch_sub(1); }
T *operator++( ) volatile noexcept { return fetch_add(1) + 1; } T *operator++( ) volatile { return fetch_add(1) + 1; }
T *operator++( ) noexcept { return fetch_add(1) + 1; } T *operator++( ) { return fetch_add(1) + 1; }
T *operator--( ) volatile noexcept { return fetch_sub(1) - 1; } T *operator--( ) volatile { return fetch_sub(1) - 1; }
T *operator--( ) noexcept { return fetch_sub(1) - 1; } T *operator--( ) { return fetch_sub(1) - 1; }
T *operator+=(ptrdiff_t op) volatile noexcept { return fetch_add(op) + op; } T *operator+=(ptrdiff_t op) volatile { return fetch_add(op) + op; }
T *operator+=(ptrdiff_t op) noexcept { return fetch_add(op) + op; } T *operator+=(ptrdiff_t op) { return fetch_add(op) + op; }
T *operator-=(ptrdiff_t op) volatile noexcept { return fetch_sub(op) - op; } T *operator-=(ptrdiff_t op) volatile { return fetch_sub(op) - op; }
T *operator-=(ptrdiff_t op) noexcept { return fetch_sub(op) - op; } T *operator-=(ptrdiff_t op) { return fetch_sub(op) - op; }
}; };
template<typename T> template<typename T>
inline bool atomic_is_lock_free(const volatile Atomic<T> *a) noexcept { inline bool atomic_is_lock_free(const volatile Atomic<T> *a) {
return a->is_lock_free(); return a->is_lock_free();
} }
template<typename T> template<typename T>
inline bool atomic_is_lock_free(const Atomic<T> *a) noexcept { inline bool atomic_is_lock_free(const Atomic<T> *a) {
return a->is_lock_free(); return a->is_lock_free();
} }
template<typename T> template<typename T>
inline void atomic_init(volatile Atomic<T> *a, T v) noexcept { inline void atomic_init(volatile Atomic<T> *a, T v) {
__octa_atomic_init(&a->p_a, v); __octa_atomic_init(&a->p_a, v);
} }
template<typename T> template<typename T>
inline void atomic_init(Atomic<T> *a, T v) noexcept { inline void atomic_init(Atomic<T> *a, T v) {
__octa_atomic_init(&a->p_a, v); __octa_atomic_init(&a->p_a, v);
} }
template <typename T> template <typename T>
inline void atomic_store(volatile Atomic<T> *a, T v) noexcept { inline void atomic_store(volatile Atomic<T> *a, T v) {
a->store(v); a->store(v);
} }
template <typename T> template <typename T>
inline void atomic_store(Atomic<T> *a, T v) noexcept { inline void atomic_store(Atomic<T> *a, T v) {
a->store(v); a->store(v);
} }
template <typename T> template <typename T>
inline void atomic_store_explicit(volatile Atomic<T> *a, T v, inline void atomic_store_explicit(volatile Atomic<T> *a, T v,
MemoryOrder ord) MemoryOrder ord) {
noexcept {
a->store(v, ord); a->store(v, ord);
} }
template <typename T> template <typename T>
inline void atomic_store_explicit(Atomic<T> *a, T v, MemoryOrder ord) inline void atomic_store_explicit(Atomic<T> *a, T v, MemoryOrder ord) {
noexcept {
a->store(v, ord); a->store(v, ord);
} }
template <typename T> template <typename T>
inline T atomic_load(const volatile Atomic<T> *a) noexcept { inline T atomic_load(const volatile Atomic<T> *a) {
return a->load(); return a->load();
} }
template <typename T> template <typename T>
inline T atomic_load(const Atomic<T> *a) noexcept { inline T atomic_load(const Atomic<T> *a) {
return a->load(); return a->load();
} }
template <typename T> template <typename T>
inline T atomic_load_explicit(const volatile Atomic<T> *a, inline T atomic_load_explicit(const volatile Atomic<T> *a,
MemoryOrder ord) MemoryOrder ord) {
noexcept {
return a->load(ord); return a->load(ord);
} }
template <typename T> template <typename T>
inline T atomic_load_explicit(const Atomic<T> *a, MemoryOrder ord) inline T atomic_load_explicit(const Atomic<T> *a, MemoryOrder ord) {
noexcept {
return a->load(ord); return a->load(ord);
} }
template <typename T> template <typename T>
inline T atomic_exchange(volatile Atomic<T> *a, T v) noexcept { inline T atomic_exchange(volatile Atomic<T> *a, T v) {
return a->exchange(v); return a->exchange(v);
} }
template <typename T> template <typename T>
inline T atomic_exchange(Atomic<T> *a, T v) noexcept { inline T atomic_exchange(Atomic<T> *a, T v) {
return a->exchange(v); return a->exchange(v);
} }
template <typename T> template <typename T>
inline T atomic_exchange_explicit(volatile Atomic<T> *a, T v, inline T atomic_exchange_explicit(volatile Atomic<T> *a, T v,
MemoryOrder ord) MemoryOrder ord) {
noexcept {
return a->exchange(v, ord); return a->exchange(v, ord);
} }
template <typename T> template <typename T>
inline T atomic_exchange_explicit(Atomic<T> *a, T v, MemoryOrder ord) inline T atomic_exchange_explicit(Atomic<T> *a, T v, MemoryOrder ord) {
noexcept {
return a->exchange(v, ord); return a->exchange(v, ord);
} }
template <typename T> template <typename T>
inline bool atomic_compare_exchange_weak(volatile Atomic<T> *a, T *e, T v) inline bool atomic_compare_exchange_weak(volatile Atomic<T> *a, T *e, T v) {
noexcept {
return a->compare_exchange_weak(*e, v); return a->compare_exchange_weak(*e, v);
} }
template <typename T> template <typename T>
inline bool atomic_compare_exchange_weak(Atomic<T> *a, T *e, T v) noexcept { inline bool atomic_compare_exchange_weak(Atomic<T> *a, T *e, T v) {
return a->compare_exchange_weak(*e, v); return a->compare_exchange_weak(*e, v);
} }
template <typename T> template <typename T>
inline bool atomic_compare_exchange_strong(volatile Atomic<T> *a, T *e, T v) inline bool atomic_compare_exchange_strong(volatile Atomic<T> *a, T *e, T v) {
noexcept {
return a->compare_exchange_strong(*e, v); return a->compare_exchange_strong(*e, v);
} }
template <typename T> template <typename T>
inline bool atomic_compare_exchange_strong(Atomic<T> *a, T *e, T v) inline bool atomic_compare_exchange_strong(Atomic<T> *a, T *e, T v) {
noexcept {
return a->compare_exchange_strong(*e, v); return a->compare_exchange_strong(*e, v);
} }
@ -1026,16 +988,14 @@ namespace octa {
inline bool atomic_compare_exchange_weak_explicit(volatile Atomic<T> *a, inline bool atomic_compare_exchange_weak_explicit(volatile Atomic<T> *a,
T *e, T v, T *e, T v,
MemoryOrder s, MemoryOrder s,
MemoryOrder f) MemoryOrder f) {
noexcept {
return a->compare_exchange_weak(*e, v, s, f); return a->compare_exchange_weak(*e, v, s, f);
} }
template <typename T> template <typename T>
inline bool atomic_compare_exchange_weak_explicit(Atomic<T> *a, T *e, T v, inline bool atomic_compare_exchange_weak_explicit(Atomic<T> *a, T *e, T v,
MemoryOrder s, MemoryOrder s,
MemoryOrder f) MemoryOrder f) {
noexcept {
return a->compare_exchange_weak(*e, v, s, f); return a->compare_exchange_weak(*e, v, s, f);
} }
@ -1043,267 +1003,250 @@ namespace octa {
inline bool atomic_compare_exchange_strong_explicit(volatile Atomic<T> *a, inline bool atomic_compare_exchange_strong_explicit(volatile Atomic<T> *a,
T *e, T v, T *e, T v,
MemoryOrder s, MemoryOrder s,
MemoryOrder f) MemoryOrder f) {
noexcept {
return a->compare_exchange_strong(*e, v, s, f); return a->compare_exchange_strong(*e, v, s, f);
} }
template <typename T> template <typename T>
inline bool atomic_compare_exchange_strong_explicit(Atomic<T> *a, T *e, T v, inline bool atomic_compare_exchange_strong_explicit(Atomic<T> *a, T *e, T v,
MemoryOrder s, MemoryOrder s,
MemoryOrder f) MemoryOrder f) {
noexcept {
return a->compare_exchange_strong(*e, v, s, f); return a->compare_exchange_strong(*e, v, s, f);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_add(volatile Atomic<T> *a, T op) noexcept { atomic_fetch_add(volatile Atomic<T> *a, T op) {
return a->fetch_add(op); return a->fetch_add(op);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_add(Atomic<T> *a, T op) noexcept { atomic_fetch_add(Atomic<T> *a, T op) {
return a->fetch_add(op); return a->fetch_add(op);
} }
template <typename T> template <typename T>
inline T *atomic_fetch_add(volatile Atomic<T *> *a, ptrdiff_t op) noexcept { inline T *atomic_fetch_add(volatile Atomic<T *> *a, ptrdiff_t op) {
return a->fetch_add(op); return a->fetch_add(op);
} }
template <typename T> template <typename T>
inline T *atomic_fetch_add(Atomic<T *> *a, ptrdiff_t op) noexcept { inline T *atomic_fetch_add(Atomic<T *> *a, ptrdiff_t op) {
return a->fetch_add(op); return a->fetch_add(op);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_add_explicit(volatile Atomic<T> *a, T op, MemoryOrder ord) atomic_fetch_add_explicit(volatile Atomic<T> *a, T op, MemoryOrder ord) {
noexcept {
return a->fetch_add(op, ord); return a->fetch_add(op, ord);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_add_explicit(Atomic<T> *a, T op, MemoryOrder ord) noexcept { atomic_fetch_add_explicit(Atomic<T> *a, T op, MemoryOrder ord) {
return a->fetch_add(op, ord); return a->fetch_add(op, ord);
} }
template <typename T> template <typename T>
inline T *atomic_fetch_add_explicit(volatile Atomic<T *> *a, ptrdiff_t op, inline T *atomic_fetch_add_explicit(volatile Atomic<T *> *a, ptrdiff_t op,
MemoryOrder ord) MemoryOrder ord) {
noexcept {
return a->fetch_add(op, ord); return a->fetch_add(op, ord);
} }
template <typename T> template <typename T>
inline T *atomic_fetch_add_explicit(Atomic<T *> *a, ptrdiff_t op, inline T *atomic_fetch_add_explicit(Atomic<T *> *a, ptrdiff_t op,
MemoryOrder ord) MemoryOrder ord) {
noexcept {
return a->fetch_add(op, ord); return a->fetch_add(op, ord);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_sub(volatile Atomic<T> *a, T op) noexcept { atomic_fetch_sub(volatile Atomic<T> *a, T op) {
return a->fetch_sub(op); return a->fetch_sub(op);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_sub(Atomic<T> *a, T op) noexcept { atomic_fetch_sub(Atomic<T> *a, T op) {
return a->fetch_sub(op); return a->fetch_sub(op);
} }
template <typename T> template <typename T>
inline T *atomic_fetch_sub(volatile Atomic<T *> *a, ptrdiff_t op) noexcept { inline T *atomic_fetch_sub(volatile Atomic<T *> *a, ptrdiff_t op) {
return a->fetch_sub(op); return a->fetch_sub(op);
} }
template <typename T> template <typename T>
inline T *atomic_fetch_sub(Atomic<T *> *a, ptrdiff_t op) noexcept { inline T *atomic_fetch_sub(Atomic<T *> *a, ptrdiff_t op) {
return a->fetch_sub(op); return a->fetch_sub(op);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_sub_explicit(volatile Atomic<T> *a, T op, MemoryOrder ord) atomic_fetch_sub_explicit(volatile Atomic<T> *a, T op, MemoryOrder ord) {
noexcept {
return a->fetch_sub(op, ord); return a->fetch_sub(op, ord);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_sub_explicit(Atomic<T> *a, T op, MemoryOrder ord) noexcept { atomic_fetch_sub_explicit(Atomic<T> *a, T op, MemoryOrder ord) {
return a->fetch_sub(op, ord); return a->fetch_sub(op, ord);
} }
template <typename T> template <typename T>
inline T *atomic_fetch_sub_explicit(volatile Atomic<T *> *a, ptrdiff_t op, inline T *atomic_fetch_sub_explicit(volatile Atomic<T *> *a, ptrdiff_t op,
MemoryOrder ord) MemoryOrder ord) {
noexcept {
return a->fetch_sub(op, ord); return a->fetch_sub(op, ord);
} }
template <typename T> template <typename T>
inline T *atomic_fetch_sub_explicit(Atomic<T *> *a, ptrdiff_t op, inline T *atomic_fetch_sub_explicit(Atomic<T *> *a, ptrdiff_t op,
MemoryOrder ord) MemoryOrder ord) {
noexcept {
return a->fetch_sub(op, ord); return a->fetch_sub(op, ord);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_and(volatile Atomic<T> *a, T op) noexcept { atomic_fetch_and(volatile Atomic<T> *a, T op) {
return a->fetch_and(op); return a->fetch_and(op);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_and(Atomic<T> *a, T op) noexcept { atomic_fetch_and(Atomic<T> *a, T op) {
return a->fetch_and(op); return a->fetch_and(op);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_and_explicit(volatile Atomic<T> *a, T op, MemoryOrder ord) atomic_fetch_and_explicit(volatile Atomic<T> *a, T op, MemoryOrder ord) {
noexcept {
return a->fetch_and(op, ord); return a->fetch_and(op, ord);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_and_explicit(Atomic<T> *a, T op, MemoryOrder ord) noexcept { atomic_fetch_and_explicit(Atomic<T> *a, T op, MemoryOrder ord) {
return a->fetch_and(op, ord); return a->fetch_and(op, ord);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_or(volatile Atomic<T> *a, T op) noexcept { atomic_fetch_or(volatile Atomic<T> *a, T op) {
return a->fetch_or(op); return a->fetch_or(op);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_or(Atomic<T> *a, T op) noexcept { atomic_fetch_or(Atomic<T> *a, T op) {
return a->fetch_or(op); return a->fetch_or(op);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_or_explicit(volatile Atomic<T> *a, T op, MemoryOrder ord) atomic_fetch_or_explicit(volatile Atomic<T> *a, T op, MemoryOrder ord) {
noexcept {
return a->fetch_or(op, ord); return a->fetch_or(op, ord);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_or_explicit(Atomic<T> *a, T op, MemoryOrder ord) noexcept { atomic_fetch_or_explicit(Atomic<T> *a, T op, MemoryOrder ord) {
return a->fetch_or(op, ord); return a->fetch_or(op, ord);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_xor(volatile Atomic<T> *a, T op) noexcept { atomic_fetch_xor(volatile Atomic<T> *a, T op) {
return a->fetch_xor(op); return a->fetch_xor(op);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_xor(Atomic<T> *a, T op) noexcept { atomic_fetch_xor(Atomic<T> *a, T op) {
return a->fetch_xor(op); return a->fetch_xor(op);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_xor_explicit(volatile Atomic<T> *a, T op, MemoryOrder ord) atomic_fetch_xor_explicit(volatile Atomic<T> *a, T op, MemoryOrder ord) {
noexcept {
return a->fetch_xor(op, ord); return a->fetch_xor(op, ord);
} }
template <typename T> template <typename T>
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T> inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
atomic_fetch_xor_explicit(Atomic<T> *a, T op, MemoryOrder ord) noexcept { atomic_fetch_xor_explicit(Atomic<T> *a, T op, MemoryOrder ord) {
return a->fetch_xor(op, ord); return a->fetch_xor(op, ord);
} }
struct AtomicFlag { struct AtomicFlag {
__OctaAtomicBase<bool> p_a; __OctaAtomicBase<bool> p_a;
AtomicFlag() noexcept = default; AtomicFlag() = default;
AtomicFlag(bool b) noexcept: p_a(b) {} AtomicFlag(bool b): p_a(b) {}
AtomicFlag(const AtomicFlag &) = delete; AtomicFlag(const AtomicFlag &) = delete;
AtomicFlag &operator=(const AtomicFlag &) = delete; AtomicFlag &operator=(const AtomicFlag &) = delete;
AtomicFlag &operator=(const AtomicFlag &) volatile = delete; AtomicFlag &operator=(const AtomicFlag &) volatile = delete;
bool test_and_set(MemoryOrder ord = MemoryOrder::seq_cst) bool test_and_set(MemoryOrder ord = MemoryOrder::seq_cst) volatile {
volatile noexcept {
return __octa_atomic_exchange(&p_a, true, ord); return __octa_atomic_exchange(&p_a, true, ord);
} }
bool test_and_set(MemoryOrder ord = MemoryOrder::seq_cst) noexcept { bool test_and_set(MemoryOrder ord = MemoryOrder::seq_cst) {
return __octa_atomic_exchange(&p_a, true, ord); return __octa_atomic_exchange(&p_a, true, ord);
} }
void clear(MemoryOrder ord = MemoryOrder::seq_cst) volatile noexcept { void clear(MemoryOrder ord = MemoryOrder::seq_cst) volatile {
__octa_atomic_store(&p_a, false, ord); __octa_atomic_store(&p_a, false, ord);
} }
void clear(MemoryOrder ord = MemoryOrder::seq_cst) noexcept { void clear(MemoryOrder ord = MemoryOrder::seq_cst) {
__octa_atomic_store(&p_a, false, ord); __octa_atomic_store(&p_a, false, ord);
} }
}; };
inline bool atomic_flag_test_and_set(volatile AtomicFlag *a) inline bool atomic_flag_test_and_set(volatile AtomicFlag *a) {
noexcept {
return a->test_and_set(); return a->test_and_set();
} }
inline bool atomic_flag_test_and_set(AtomicFlag *a) noexcept { inline bool atomic_flag_test_and_set(AtomicFlag *a) {
return a->test_and_set(); return a->test_and_set();
} }
inline bool atomic_flag_test_and_set_explicit(volatile AtomicFlag *a, inline bool atomic_flag_test_and_set_explicit(volatile AtomicFlag *a,
MemoryOrder ord) MemoryOrder ord) {
noexcept {
return a->test_and_set(ord); return a->test_and_set(ord);
} }
inline bool atomic_flag_test_and_set_explicit(AtomicFlag *a, inline bool atomic_flag_test_and_set_explicit(AtomicFlag *a,
MemoryOrder ord) MemoryOrder ord) {
noexcept {
return a->test_and_set(ord); return a->test_and_set(ord);
} }
inline void atomic_flag_clear(volatile AtomicFlag *a) noexcept { inline void atomic_flag_clear(volatile AtomicFlag *a) {
a->clear(); a->clear();
} }
inline void atomic_flag_clear(AtomicFlag *a) noexcept { inline void atomic_flag_clear(AtomicFlag *a) {
a->clear(); a->clear();
} }
inline void atomic_flag_clear_explicit(volatile AtomicFlag *a, inline void atomic_flag_clear_explicit(volatile AtomicFlag *a,
MemoryOrder ord) MemoryOrder ord) {
noexcept {
a->clear(ord); a->clear(ord);
} }
inline void atomic_flag_clear_explicit(AtomicFlag *a, MemoryOrder ord) inline void atomic_flag_clear_explicit(AtomicFlag *a, MemoryOrder ord) {
noexcept {
a->clear(ord); a->clear(ord);
} }
inline void atomic_thread_fence(MemoryOrder ord) noexcept { inline void atomic_thread_fence(MemoryOrder ord) {
__octa_atomic_thread_fence(ord); __octa_atomic_thread_fence(ord);
} }
inline void atomic_signal_fence(MemoryOrder ord) noexcept { inline void atomic_signal_fence(MemoryOrder ord) {
__octa_atomic_signal_fence(ord); __octa_atomic_signal_fence(ord);
} }

View File

@ -16,9 +16,7 @@ namespace octa {
#define __OCTA_DEFINE_BINARY_OP(name, op, rettype) \ #define __OCTA_DEFINE_BINARY_OP(name, op, rettype) \
template<typename T> struct name { \ template<typename T> struct name { \
bool operator()(const T &x, const T &y) const noexcept( \ bool operator()(const T &x, const T &y) const { return x op y; } \
noexcept(x op y) \
) { return x op y; } \
typedef T FirstArgType; \ typedef T FirstArgType; \
typedef T SecondArgType; \ typedef T SecondArgType; \
typedef rettype ResultType; \ typedef rettype ResultType; \
@ -44,13 +42,13 @@ namespace octa {
#undef __OCTA_DEFINE_BINARY_OP #undef __OCTA_DEFINE_BINARY_OP
template<typename T> struct LogicalNot { template<typename T> struct LogicalNot {
bool operator()(const T &x) const noexcept(noexcept(!x)) { return !x; } bool operator()(const T &x) const { return !x; }
typedef T ArgType; typedef T ArgType;
typedef bool ResultType; typedef bool ResultType;
}; };
template<typename T> struct Negate { template<typename T> struct Negate {
bool operator()(const T &x) const noexcept(noexcept(-x)) { return -x; } bool operator()(const T &x) const { return -x; }
typedef T ArgType; typedef T ArgType;
typedef T ResultType; typedef T ResultType;
}; };
@ -60,14 +58,10 @@ namespace octa {
typedef typename T::SecondArgType SecondArgType; typedef typename T::SecondArgType SecondArgType;
typedef bool ResultType; typedef bool ResultType;
explicit BinaryNegate(const T &f) noexcept( explicit BinaryNegate(const T &f): p_fn(f) {}
IsNothrowCopyConstructible<T>::value
): p_fn(f) {}
bool operator()(const FirstArgType &x, bool operator()(const FirstArgType &x,
const SecondArgType &y) noexcept( const SecondArgType &y) {
noexcept(p_fn(x, y))
) {
return !p_fn(x, y); return !p_fn(x, y);
} }
private: private:
@ -78,25 +72,19 @@ namespace octa {
typedef typename T::ArgType ArgType; typedef typename T::ArgType ArgType;
typedef bool ResultType; typedef bool ResultType;
explicit UnaryNegate(const T &f) noexcept( explicit UnaryNegate(const T &f): p_fn(f) {}
IsNothrowCopyConstructible<T>::value bool operator()(const ArgType &x) {
): p_fn(f) {}
bool operator()(const ArgType &x) noexcept(noexcept(p_fn(x))) {
return !p_fn(x); return !p_fn(x);
} }
private: private:
T p_fn; T p_fn;
}; };
template<typename T> UnaryNegate<T> not1(const T &fn) noexcept( template<typename T> UnaryNegate<T> not1(const T &fn) {
IsNothrowCopyConstructible<UnaryNegate<T>>::value
) {
return UnaryNegate<T>(fn); return UnaryNegate<T>(fn);
} }
template<typename T> BinaryNegate<T> not2(const T &fn) noexcept( template<typename T> BinaryNegate<T> not2(const T &fn) {
IsNothrowCopyConstructible<BinaryNegate<T>>::value
) {
return BinaryNegate<T>(fn); return BinaryNegate<T>(fn);
} }
@ -108,7 +96,7 @@ namespace octa {
typedef T ArgType; typedef T ArgType;
typedef size_t ResultType; typedef size_t ResultType;
size_t operator()(T v) const noexcept { size_t operator()(T v) const {
return (size_t)v; return (size_t)v;
} }
}; };
@ -145,7 +133,7 @@ namespace octa {
typedef T ArgType; typedef T ArgType;
typedef size_t ResultType; typedef size_t ResultType;
size_t operator()(T v) const noexcept { size_t operator()(T v) const {
union { T v; size_t h; } u; union { T v; size_t h; } u;
u.h = 0; u.h = 0;
u.v = v; u.v = v;
@ -157,7 +145,7 @@ namespace octa {
typedef T ArgType; typedef T ArgType;
typedef size_t ResultType; typedef size_t ResultType;
size_t operator()(T v) const noexcept { size_t operator()(T v) const {
union { T v; size_t h; } u; union { T v; size_t h; } u;
u.v = v; u.v = v;
return u.h; return u.h;
@ -168,7 +156,7 @@ namespace octa {
typedef T ArgType; typedef T ArgType;
typedef size_t ResultType; typedef size_t ResultType;
size_t operator()(T v) const noexcept { size_t operator()(T v) const {
union { T v; struct { size_t h1, h2; }; } u; union { T v; struct { size_t h1, h2; }; } u;
u.v = v; u.v = v;
return __octa_mem_hash((const void *)&u, sizeof(u)); return __octa_mem_hash((const void *)&u, sizeof(u));
@ -179,7 +167,7 @@ namespace octa {
typedef T ArgType; typedef T ArgType;
typedef size_t ResultType; typedef size_t ResultType;
size_t operator()(T v) const noexcept { size_t operator()(T v) const {
union { T v; struct { size_t h1, h2, h3; }; } u; union { T v; struct { size_t h1, h2, h3; }; } u;
u.v = v; u.v = v;
return __octa_mem_hash((const void *)&u, sizeof(u)); return __octa_mem_hash((const void *)&u, sizeof(u));
@ -190,7 +178,7 @@ namespace octa {
typedef T ArgType; typedef T ArgType;
typedef size_t ResultType; typedef size_t ResultType;
size_t operator()(T v) const noexcept { size_t operator()(T v) const {
union { T v; struct { size_t h1, h2, h3, h4; }; } u; union { T v; struct { size_t h1, h2, h3, h4; }; } u;
u.v = v; u.v = v;
return __octa_mem_hash((const void *)&u, sizeof(u)); return __octa_mem_hash((const void *)&u, sizeof(u));
@ -201,21 +189,21 @@ namespace octa {
template<> struct Hash<ullong>: __OctaScalarHash<ullong> {}; template<> struct Hash<ullong>: __OctaScalarHash<ullong> {};
template<> struct Hash<float>: __OctaScalarHash<float> { template<> struct Hash<float>: __OctaScalarHash<float> {
size_t operator()(float v) const noexcept { size_t operator()(float v) const {
if (v == 0) return 0; if (v == 0) return 0;
return __OctaScalarHash<float>::operator()(v); return __OctaScalarHash<float>::operator()(v);
} }
}; };
template<> struct Hash<double>: __OctaScalarHash<double> { template<> struct Hash<double>: __OctaScalarHash<double> {
size_t operator()(double v) const noexcept { size_t operator()(double v) const {
if (v == 0) return 0; if (v == 0) return 0;
return __OctaScalarHash<double>::operator()(v); return __OctaScalarHash<double>::operator()(v);
} }
}; };
template<> struct Hash<ldouble>: __OctaScalarHash<ldouble> { template<> struct Hash<ldouble>: __OctaScalarHash<ldouble> {
size_t operator()(ldouble v) const noexcept { size_t operator()(ldouble v) const {
if (v == 0) return 0; if (v == 0) return 0;
#ifdef __i386__ #ifdef __i386__
union { ldouble v; struct { size_t h1, h2, h3, h4; }; } u; union { ldouble v; struct { size_t h1, h2, h3, h4; }; } u;
@ -239,7 +227,7 @@ namespace octa {
typedef T *ArgType; typedef T *ArgType;
typedef size_t ResultType; typedef size_t ResultType;
size_t operator()(T *v) const noexcept { size_t operator()(T *v) const {
union { T *v; size_t h; } u; union { T *v; size_t h; } u;
u.v = v; u.v = v;
return __octa_mem_hash((const void *)&u, sizeof(u)); return __octa_mem_hash((const void *)&u, sizeof(u));
@ -252,7 +240,7 @@ namespace octa {
struct ReferenceWrapper { struct ReferenceWrapper {
typedef T type; typedef T type;
ReferenceWrapper(T &v) noexcept: p_ptr(address_of(v)) {} ReferenceWrapper(T &v): p_ptr(address_of(v)) {}
ReferenceWrapper(const ReferenceWrapper &) = default; ReferenceWrapper(const ReferenceWrapper &) = default;
ReferenceWrapper(T &&) = delete; ReferenceWrapper(T &&) = delete;
@ -266,21 +254,21 @@ namespace octa {
}; };
template<typename T> template<typename T>
ReferenceWrapper<T> ref(T &v) noexcept { ReferenceWrapper<T> ref(T &v) {
return ReferenceWrapper<T>(v); return ReferenceWrapper<T>(v);
} }
template<typename T> template<typename T>
ReferenceWrapper<T> ref(ReferenceWrapper<T> v) noexcept { ReferenceWrapper<T> ref(ReferenceWrapper<T> v) {
return ReferenceWrapper<T>(v); return ReferenceWrapper<T>(v);
} }
template<typename T> void ref(const T &&) = delete; template<typename T> void ref(const T &&) = delete;
template<typename T> template<typename T>
ReferenceWrapper<const T> cref(const T &v) noexcept { ReferenceWrapper<const T> cref(const T &v) {
return ReferenceWrapper<T>(v); return ReferenceWrapper<T>(v);
} }
template<typename T> template<typename T>
ReferenceWrapper<const T> cref(ReferenceWrapper<T> v) noexcept { ReferenceWrapper<const T> cref(ReferenceWrapper<T> v) {
return ReferenceWrapper<T>(v); return ReferenceWrapper<T>(v);
} }
template<typename T> void cref(const T &&) = delete; template<typename T> void cref(const T &&) = delete;
@ -339,7 +327,7 @@ namespace octa {
}; };
template<typename R, typename T> template<typename R, typename T>
__OctaMemFn<R, T> mem_fn(R T:: *ptr) noexcept { __OctaMemFn<R, T> mem_fn(R T:: *ptr) {
return __OctaMemFn<R, T>(ptr); return __OctaMemFn<R, T>(ptr);
} }
@ -357,7 +345,7 @@ namespace octa {
struct __OctaFunctorInPlace { struct __OctaFunctorInPlace {
static constexpr bool value = sizeof(T) <= sizeof(__OctaFunctorData) static constexpr bool value = sizeof(T) <= sizeof(__OctaFunctorData)
&& (alignof(__OctaFunctorData) % alignof(T)) == 0 && (alignof(__OctaFunctorData) % alignof(T)) == 0
&& octa::IsNothrowMoveConstructible<T>(); && octa::IsMoveConstructible<T>::value;
}; };
template<typename T, typename E = void> template<typename T, typename E = void>
@ -371,15 +359,15 @@ namespace octa {
new (&get_ref(s)) T(forward<T>(v)); new (&get_ref(s)) T(forward<T>(v));
} }
static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) noexcept { static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) {
new (&get_ref(lhs)) T(move(get_ref(rhs))); new (&get_ref(lhs)) T(move(get_ref(rhs)));
} }
static void destroy_f(__OctaFunctorData &s) noexcept { static void destroy_f(__OctaFunctorData &s) {
get_ref(s).~T(); get_ref(s).~T();
} }
static T &get_ref(const __OctaFunctorData &s) noexcept { static T &get_ref(const __OctaFunctorData &s) {
return (T &)s; return (T &)s;
} }
}; };
@ -395,27 +383,27 @@ namespace octa {
new (&get_ptr_ref(s)) T *(new T(forward<T>(v))); new (&get_ptr_ref(s)) T *(new T(forward<T>(v)));
} }
static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) noexcept { static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) {
new (&get_ptr_ref(lhs)) T *(get_ptr_ref(rhs)); new (&get_ptr_ref(lhs)) T *(get_ptr_ref(rhs));
get_ptr_ref(rhs) = nullptr; get_ptr_ref(rhs) = nullptr;
} }
static void destroy_f(__OctaFunctorData &s) noexcept { static void destroy_f(__OctaFunctorData &s) {
T *&ptr = get_ptr_ref(s); T *&ptr = get_ptr_ref(s);
if (!ptr) return; if (!ptr) return;
delete ptr; delete ptr;
ptr = nullptr; ptr = nullptr;
} }
static T &get_ref(const __OctaFunctorData &s) noexcept { static T &get_ref(const __OctaFunctorData &s) {
return *get_ptr_ref(s); return *get_ptr_ref(s);
} }
static T *&get_ptr_ref(__OctaFunctorData &s) noexcept { static T *&get_ptr_ref(__OctaFunctorData &s) {
return (T *&)s; return (T *&)s;
} }
static T *&get_ptr_ref(const __OctaFunctorData &s) noexcept { static T *&get_ptr_ref(const __OctaFunctorData &s) {
return (T *&)s; return (T *&)s;
} }
}; };
@ -537,22 +525,21 @@ namespace octa {
template<typename R, typename ...A> template<typename R, typename ...A>
struct Function<R(A...)>: __OctaFunction<R, A...> { struct Function<R(A...)>: __OctaFunction<R, A...> {
Function( ) noexcept { initialize_empty(); } Function( ) { initialize_empty(); }
Function(nullptr_t) noexcept { initialize_empty(); } Function(nullptr_t) { initialize_empty(); }
Function(Function &&f) noexcept { Function(Function &&f) {
initialize_empty(); initialize_empty();
swap(f); swap(f);
} }
Function(const Function &f) noexcept: p_call(f.p_call) { Function(const Function &f): p_call(f.p_call) {
f.p_stor.manager->call_copy(p_stor, f.p_stor); f.p_stor.manager->call_copy(p_stor, f.p_stor);
} }
template<typename T> template<typename T>
Function(T f, EnableIf<IsValidFunctor<T, R(A...)>::value, __OctaEmpty> Function(T f, EnableIf<IsValidFunctor<T, R(A...)>::value, __OctaEmpty>
= __OctaEmpty()) = __OctaEmpty()) {
noexcept(__OctaFunctorInPlace<T>::value) {
if (func_is_null(f)) { if (func_is_null(f)) {
initialize_empty(); initialize_empty();
return; return;
@ -564,13 +551,13 @@ namespace octa {
p_stor.manager->call_destroy(p_stor); p_stor.manager->call_destroy(p_stor);
} }
Function &operator=(Function &&f) noexcept { Function &operator=(Function &&f) {
p_stor.manager->call_destroy(p_stor); p_stor.manager->call_destroy(p_stor);
swap(f); swap(f);
return *this; return *this;
} }
Function &operator=(const Function &f) noexcept { Function &operator=(const Function &f) {
p_stor.manager->call_destroy(p_stor); p_stor.manager->call_destroy(p_stor);
f.p_stor.manager->call_copy(p_stor, f.p_stor); f.p_stor.manager->call_copy(p_stor, f.p_stor);
return *this; return *this;
@ -580,12 +567,11 @@ namespace octa {
return p_call(p_stor.data, forward<A>(args)...); return p_call(p_stor.data, forward<A>(args)...);
} }
template<typename F> template<typename F> void assign(F &&f) {
void assign(F &&f) noexcept(__OctaFunctorInPlace<F>::value) {
Function(forward<F>(f)).swap(*this); Function(forward<F>(f)).swap(*this);
} }
void swap(Function &f) noexcept { void swap(Function &f) {
__OctaFmStorage tmp; __OctaFmStorage tmp;
f.p_stor.manager->call_move_and_destroy(tmp, move(f.p_stor)); f.p_stor.manager->call_move_and_destroy(tmp, move(f.p_stor));
p_stor.manager->call_move_and_destroy(f.p_stor, move(p_stor)); p_stor.manager->call_move_and_destroy(f.p_stor, move(p_stor));
@ -593,7 +579,7 @@ namespace octa {
octa::swap(p_call, f.p_call); octa::swap(p_call, f.p_call);
} }
operator bool() const noexcept { return p_call != nullptr; } operator bool() const { return p_call != nullptr; }
private: private:
__OctaFmStorage p_stor; __OctaFmStorage p_stor;
@ -606,7 +592,7 @@ namespace octa {
__OctaFunctorDataManager<T>::store_f(p_stor.data, forward<T>(f)); __OctaFunctorDataManager<T>::store_f(p_stor.data, forward<T>(f));
} }
void initialize_empty() noexcept { void initialize_empty() {
typedef R(*emptyf)(A...); typedef R(*emptyf)(A...);
p_call = nullptr; p_call = nullptr;
p_stor.manager = &__octa_get_default_fm<emptyf>(); p_stor.manager = &__octa_get_default_fm<emptyf>();
@ -632,21 +618,21 @@ namespace octa {
}; };
template<typename T> template<typename T>
void swap(Function<T> &a, Function<T> &b) noexcept { void swap(Function<T> &a, Function<T> &b) {
a.swap(b); a.swap(b);
} }
template<typename T> template<typename T>
bool operator==(nullptr_t, const Function<T> &rhs) noexcept { return !rhs; } bool operator==(nullptr_t, const Function<T> &rhs) { return !rhs; }
template<typename T> template<typename T>
bool operator==(const Function<T> &lhs, nullptr_t) noexcept { return !lhs; } bool operator==(const Function<T> &lhs, nullptr_t) { return !lhs; }
template<typename T> template<typename T>
bool operator!=(nullptr_t, const Function<T> &rhs) noexcept { return rhs; } bool operator!=(nullptr_t, const Function<T> &rhs) { return rhs; }
template<typename T> template<typename T>
bool operator!=(const Function<T> &lhs, nullptr_t) noexcept { return lhs; } bool operator!=(const Function<T> &lhs, nullptr_t) { return lhs; }
} }
#endif #endif

View File

@ -17,7 +17,7 @@ namespace std {
const T *p_buf; const T *p_buf;
size_t p_len; size_t p_len;
initializer_list(const T *v, size_t n) noexcept: p_buf(v), p_len(n) {} initializer_list(const T *v, size_t n): p_buf(v), p_len(n) {}
public: public:
typedef size_t SizeType; typedef size_t SizeType;
typedef ptrdiff_t DiffType; typedef ptrdiff_t DiffType;
@ -27,13 +27,13 @@ namespace std {
typedef T *PtrType; typedef T *PtrType;
typedef const T *ConstPtrType; typedef const T *ConstPtrType;
initializer_list() noexcept: p_buf(nullptr), p_len(0) {} initializer_list(): p_buf(nullptr), p_len(0) {}
size_t length() const noexcept { return p_len; } size_t length() const { return p_len; }
const T *get() const noexcept { return p_buf; } const T *get() const { return p_buf; }
octa::PointerRange<const T> range() noexcept { octa::PointerRange<const T> range() {
return octa::PointerRange<const T>(p_buf, p_len); return octa::PointerRange<const T>(p_buf, p_len);
} }
}; };

View File

@ -15,7 +15,7 @@
namespace octa { namespace octa {
/* address of */ /* address of */
template<typename T> constexpr T *address_of(T &v) noexcept { template<typename T> constexpr T *address_of(T &v) {
return reinterpret_cast<T *>(&const_cast<char &> return reinterpret_cast<T *>(&const_cast<char &>
(reinterpret_cast<const volatile char &>(v))); (reinterpret_cast<const volatile char &>(v)));
} }
@ -156,15 +156,15 @@ namespace octa {
struct __OctaPtrTraitsPointerTo { struct __OctaPtrTraitsPointerTo {
static T pointer_to(Conditional<IsVoid<PointerElement<T>>::value, static T pointer_to(Conditional<IsVoid<PointerElement<T>>::value,
__OctaPtrTraitsNat, PointerElement<T> __OctaPtrTraitsNat, PointerElement<T>
> &r) noexcept(noexcept(T::pointer_to(r))) { > &r) {
return T::pointer_to(r); return T::pointer_to(r);
} }
}; };
template<typename T> template<typename T>
struct __OctaPtrTraitsPointerTo<T *> { struct __OctaPtrTraitsPointerTo<T *> {
static T pointer_to(Conditional<IsVoid<T>::value, __OctaPtrTraitsNat, T> &r) static T pointer_to(Conditional<IsVoid<T>::value, __OctaPtrTraitsNat, T
noexcept { > &r) {
return octa::address_of(r); return octa::address_of(r);
} }
}; };
@ -172,7 +172,7 @@ namespace octa {
template<typename T> template<typename T>
static T pointer_to(Conditional<IsVoid<PointerElement<T>>::value, static T pointer_to(Conditional<IsVoid<PointerElement<T>>::value,
__OctaPtrTraitsNat, PointerElement<T> __OctaPtrTraitsNat, PointerElement<T>
> &r) noexcept(noexcept(__OctaPtrTraitsPointerTo<T>::pointer_to(r))) { > &r) {
return __OctaPtrTraitsPointerTo<T>::pointer_to(r); return __OctaPtrTraitsPointerTo<T>::pointer_to(r);
} }
@ -184,7 +184,7 @@ namespace octa {
template<typename U> DefaultDelete(const DefaultDelete<U> &) {}; template<typename U> DefaultDelete(const DefaultDelete<U> &) {};
void operator()(T *p) const noexcept { void operator()(T *p) const {
delete p; delete p;
} }
}; };
@ -195,7 +195,7 @@ namespace octa {
template<typename U> DefaultDelete(const DefaultDelete<U[]> &) {}; template<typename U> DefaultDelete(const DefaultDelete<U[]> &) {};
void operator()(T *p) const noexcept { void operator()(T *p) const {
delete[] p; delete[] p;
} }
template<typename U> void operator()(U *) const = delete; template<typename U> void operator()(U *) const = delete;
@ -214,13 +214,12 @@ namespace octa {
public: public:
template<typename D> template<typename D>
__OctaBoxPair(T *ptr, D &&dltr) noexcept: __OctaBoxPair(T *ptr, D &&dltr): i_ptr(ptr), p_del(forward<D>(dltr)) {}
i_ptr(ptr), p_del(forward<D>(dltr)) {}
U &get_deleter() noexcept { return p_del; } U &get_deleter() { return p_del; }
const U &get_deleter() const noexcept { return p_del; } const U &get_deleter() const { return p_del; }
void swap(__OctaBoxPair &v) noexcept { void swap(__OctaBoxPair &v) {
octa::swap(i_ptr, v.i_ptr); octa::swap(i_ptr, v.i_ptr);
octa::swap(p_del, v.p_del); octa::swap(p_del, v.p_del);
} }
@ -231,13 +230,12 @@ namespace octa {
T *i_ptr; T *i_ptr;
template<typename D> template<typename D>
__OctaBoxPair(T *ptr, D &&dltr) noexcept: __OctaBoxPair(T *ptr, D &&dltr): U(forward<D>(dltr)), i_ptr(ptr) {}
U(forward<D>(dltr)), i_ptr(ptr) {}
U &get_deleter() noexcept { return *this; } U &get_deleter() { return *this; }
const U &get_deleter() const noexcept { return *this; } const U &get_deleter() const { return *this; }
void swap(__OctaBoxPair &v) noexcept { void swap(__OctaBoxPair &v) {
octa::swap(i_ptr, v.i_ptr); octa::swap(i_ptr, v.i_ptr);
} }
}; };
@ -277,40 +275,39 @@ namespace octa {
typedef const RemoveReference<D> &D_cref; typedef const RemoveReference<D> &D_cref;
public: public:
constexpr Box() noexcept: p_stor(nullptr, D()) { constexpr Box(): p_stor(nullptr, D()) {
static_assert(!IsPointer<D>::value, static_assert(!IsPointer<D>::value,
"Box constructed with null fptr deleter"); "Box constructed with null fptr deleter");
} }
constexpr Box(nullptr_t) noexcept: p_stor(nullptr, D()) { constexpr Box(nullptr_t): p_stor(nullptr, D()) {
static_assert(!IsPointer<D>::value, static_assert(!IsPointer<D>::value,
"Box constructed with null fptr deleter"); "Box constructed with null fptr deleter");
} }
explicit Box(PtrType p) noexcept: p_stor(p, D()) { explicit Box(PtrType p): p_stor(p, D()) {
static_assert(!IsPointer<D>::value, static_assert(!IsPointer<D>::value,
"Box constructed with null fptr deleter"); "Box constructed with null fptr deleter");
} }
Box(PtrType p, Conditional<IsReference<D>::value, Box(PtrType p, Conditional<IsReference<D>::value,
D, AddLvalueReference<const D> D, AddLvalueReference<const D>
> d) noexcept: p_stor(p, d) {} > d): p_stor(p, d) {}
Box(PtrType p, RemoveReference<D> &&d) noexcept: p_stor(p, move(d)) { Box(PtrType p, RemoveReference<D> &&d): p_stor(p, move(d)) {
static_assert(!IsReference<D>::value, static_assert(!IsReference<D>::value,
"rvalue deleter cannot be a ref"); "rvalue deleter cannot be a ref");
} }
Box(Box &&u) noexcept: p_stor(u.release(), forward<D>(u.get_deleter())) {} Box(Box &&u): p_stor(u.release(), forward<D>(u.get_deleter())) {}
template<typename TT, typename DD> template<typename TT, typename DD>
Box(Box<TT, DD> &&u, EnableIf<!IsArray<TT>::value Box(Box<TT, DD> &&u, EnableIf<!IsArray<TT>::value
&& IsConvertible<typename Box<TT, DD>::PtrType, PtrType>::value && IsConvertible<typename Box<TT, DD>::PtrType, PtrType>::value
&& IsConvertible<DD, D>::value && IsConvertible<DD, D>::value
&& (!IsReference<D>::value || IsSame<D, DD>::value) && (!IsReference<D>::value || IsSame<D, DD>::value)
> = __OctaNat()) noexcept: p_stor(u.release(), > = __OctaNat()): p_stor(u.release(), forward<DD>(u.get_deleter())) {}
forward<DD>(u.get_deleter())) {}
Box &operator=(Box &&u) noexcept { Box &operator=(Box &&u) {
reset(u.release()); reset(u.release());
p_stor.get_deleter() = forward<D>(u.get_deleter()); p_stor.get_deleter() = forward<D>(u.get_deleter());
return *this; return *this;
@ -321,13 +318,13 @@ namespace octa {
&& IsConvertible<typename Box<TT, DD>::PtrType, PtrType>::value && IsConvertible<typename Box<TT, DD>::PtrType, PtrType>::value
&& IsAssignable<D &, DD &&>::value, && IsAssignable<D &, DD &&>::value,
Box & Box &
> operator=(Box<TT, DD> &&u) noexcept { > operator=(Box<TT, DD> &&u) {
reset(u.release()); reset(u.release());
p_stor.get_deleter() = forward<DD>(u.get_deleter()); p_stor.get_deleter() = forward<DD>(u.get_deleter());
return *this; return *this;
} }
Box &operator=(nullptr_t) noexcept { Box &operator=(nullptr_t) {
reset(); reset();
return *this; return *this;
} }
@ -335,30 +332,30 @@ namespace octa {
~Box() { reset(); } ~Box() { reset(); }
AddLvalueReference<T> operator*() const { return *p_stor.i_ptr; } AddLvalueReference<T> operator*() const { return *p_stor.i_ptr; }
PtrType operator->() const noexcept { return p_stor.i_ptr; } PtrType operator->() const { return p_stor.i_ptr; }
explicit operator bool() const noexcept { explicit operator bool() const {
return p_stor.i_ptr != nullptr; return p_stor.i_ptr != nullptr;
} }
PtrType get() const noexcept { return p_stor.i_ptr; } PtrType get() const { return p_stor.i_ptr; }
D_ref get_deleter() noexcept { return p_stor.get_deleter(); } D_ref get_deleter() { return p_stor.get_deleter(); }
D_cref get_deleter() const noexcept { return p_stor.get_deleter(); } D_cref get_deleter() const { return p_stor.get_deleter(); }
PtrType release() noexcept { PtrType release() {
PtrType p = p_stor.i_ptr; PtrType p = p_stor.i_ptr;
p_stor.i_ptr = nullptr; p_stor.i_ptr = nullptr;
return p; return p;
} }
void reset(PtrType p = nullptr) noexcept { void reset(PtrType p = nullptr) {
PtrType tmp = p_stor.i_ptr; PtrType tmp = p_stor.i_ptr;
p_stor.i_ptr = p; p_stor.i_ptr = p;
if (tmp) p_stor.get_deleter()(tmp); if (tmp) p_stor.get_deleter()(tmp);
} }
void swap(Box &u) noexcept { void swap(Box &u) {
p_stor.swap(u.p_stor); p_stor.swap(u.p_stor);
} }
@ -394,18 +391,18 @@ namespace octa {
typedef const RemoveReference<D> &D_cref; typedef const RemoveReference<D> &D_cref;
public: public:
constexpr Box() noexcept: p_stor(nullptr, D()) { constexpr Box(): p_stor(nullptr, D()) {
static_assert(!IsPointer<D>::value, static_assert(!IsPointer<D>::value,
"Box constructed with null fptr deleter"); "Box constructed with null fptr deleter");
} }
constexpr Box(nullptr_t) noexcept: p_stor(nullptr, D()) { constexpr Box(nullptr_t): p_stor(nullptr, D()) {
static_assert(!IsPointer<D>::value, static_assert(!IsPointer<D>::value,
"Box constructed with null fptr deleter"); "Box constructed with null fptr deleter");
} }
template<typename U> explicit Box(U p, EnableIf< template<typename U> explicit Box(U p, EnableIf<
__OctaSameOrLessCvQualified<U, PtrType>::value, __OctaNat __OctaSameOrLessCvQualified<U, PtrType>::value, __OctaNat
> = __OctaNat()) noexcept: p_stor(p, D()) { > = __OctaNat()): p_stor(p, D()) {
static_assert(!IsPointer<D>::value, static_assert(!IsPointer<D>::value,
"Box constructed with null fptr deleter"); "Box constructed with null fptr deleter");
} }
@ -413,25 +410,25 @@ namespace octa {
template<typename U> Box(U p, Conditional<IsReference<D>::value, template<typename U> Box(U p, Conditional<IsReference<D>::value,
D, AddLvalueReference<const D> D, AddLvalueReference<const D>
> d, EnableIf<__OctaSameOrLessCvQualified<U, PtrType>::value, __OctaNat > d, EnableIf<__OctaSameOrLessCvQualified<U, PtrType>::value, __OctaNat
> = __OctaNat()) noexcept: p_stor(p, d) {} > = __OctaNat()): p_stor(p, d) {}
Box(nullptr_t, Conditional<IsReference<D>::value, Box(nullptr_t, Conditional<IsReference<D>::value,
D, AddLvalueReference<const D> D, AddLvalueReference<const D>
> d) noexcept: p_stor(nullptr, d) {} > d): p_stor(nullptr, d) {}
template<typename U> Box(U p, RemoveReference<D> &&d, EnableIf< template<typename U> Box(U p, RemoveReference<D> &&d, EnableIf<
__OctaSameOrLessCvQualified<U, PtrType>::value, __OctaNat __OctaSameOrLessCvQualified<U, PtrType>::value, __OctaNat
> = __OctaNat()) noexcept: p_stor(p, move(d)) { > = __OctaNat()): p_stor(p, move(d)) {
static_assert(!IsReference<D>::value, static_assert(!IsReference<D>::value,
"rvalue deleter cannot be a ref"); "rvalue deleter cannot be a ref");
} }
Box(nullptr_t, RemoveReference<D> &&d) noexcept: p_stor(nullptr, move(d)) { Box(nullptr_t, RemoveReference<D> &&d): p_stor(nullptr, move(d)) {
static_assert(!IsReference<D>::value, static_assert(!IsReference<D>::value,
"rvalue deleter cannot be a ref"); "rvalue deleter cannot be a ref");
} }
Box(Box &&u) noexcept: p_stor(u.release(), forward<D>(u.get_deleter())) {} Box(Box &&u): p_stor(u.release(), forward<D>(u.get_deleter())) {}
template<typename TT, typename DD> template<typename TT, typename DD>
Box(Box<TT, DD> &&u, EnableIf<IsArray<TT>::value Box(Box<TT, DD> &&u, EnableIf<IsArray<TT>::value
@ -439,9 +436,9 @@ namespace octa {
PtrType>::value PtrType>::value
&& IsConvertible<DD, D>::value && IsConvertible<DD, D>::value
&& (!IsReference<D>::value || IsSame<D, DD>::value)> = __OctaNat() && (!IsReference<D>::value || IsSame<D, DD>::value)> = __OctaNat()
) noexcept: p_stor(u.release(), forward<DD>(u.get_deleter())) {} ): p_stor(u.release(), forward<DD>(u.get_deleter())) {}
Box &operator=(Box &&u) noexcept { Box &operator=(Box &&u) {
reset(u.release()); reset(u.release());
p_stor.get_deleter() = forward<D>(u.get_deleter()); p_stor.get_deleter() = forward<D>(u.get_deleter());
return *this; return *this;
@ -453,13 +450,13 @@ namespace octa {
PtrType>::value PtrType>::value
&& IsAssignable<D &, DD &&>::value, && IsAssignable<D &, DD &&>::value,
Box & Box &
> operator=(Box<TT, DD> &&u) noexcept { > operator=(Box<TT, DD> &&u) {
reset(u.release()); reset(u.release());
p_stor.get_deleter() = forward<DD>(u.get_deleter()); p_stor.get_deleter() = forward<DD>(u.get_deleter());
return *this; return *this;
} }
Box &operator=(nullptr_t) noexcept { Box &operator=(nullptr_t) {
reset(); reset();
return *this; return *this;
} }
@ -470,16 +467,16 @@ namespace octa {
return p_stor.i_ptr[idx]; return p_stor.i_ptr[idx];
} }
explicit operator bool() const noexcept { explicit operator bool() const {
return p_stor.i_ptr != nullptr; return p_stor.i_ptr != nullptr;
} }
PtrType get() const noexcept { return p_stor.i_ptr; } PtrType get() const { return p_stor.i_ptr; }
D_ref get_deleter() noexcept { return p_stor.get_deleter(); } D_ref get_deleter() { return p_stor.get_deleter(); }
D_cref get_deleter() const noexcept { return p_stor.get_deleter(); } D_cref get_deleter() const { return p_stor.get_deleter(); }
PtrType release() noexcept { PtrType release() {
PtrType p = p_stor.i_ptr; PtrType p = p_stor.i_ptr;
p_stor.i_ptr = nullptr; p_stor.i_ptr = nullptr;
return p; return p;
@ -487,23 +484,23 @@ namespace octa {
template<typename U> EnableIf< template<typename U> EnableIf<
__OctaSameOrLessCvQualified<U, PtrType>::value, void __OctaSameOrLessCvQualified<U, PtrType>::value, void
> reset(U p) noexcept { > reset(U p) {
PtrType tmp = p_stor.i_ptr; PtrType tmp = p_stor.i_ptr;
p_stor.i_ptr = p; p_stor.i_ptr = p;
if (tmp) p_stor.get_deleter()(tmp); if (tmp) p_stor.get_deleter()(tmp);
} }
void reset(nullptr_t) noexcept { void reset(nullptr_t) {
PtrType tmp = p_stor.i_ptr; PtrType tmp = p_stor.i_ptr;
p_stor.i_ptr = nullptr; p_stor.i_ptr = nullptr;
if (tmp) p_stor.get_deleter()(tmp); if (tmp) p_stor.get_deleter()(tmp);
} }
void reset() noexcept { void reset() {
reset(nullptr); reset(nullptr);
} }
void swap(Box &u) noexcept { void swap(Box &u) {
p_stor.swap(u.p_stor); p_stor.swap(u.p_stor);
} }
@ -567,16 +564,16 @@ namespace octa {
template<typename U> using Rebind = Allocator<U>; template<typename U> using Rebind = Allocator<U>;
PtrType address(RefType v) const noexcept { PtrType address(RefType v) const {
return address_of(v); return address_of(v);
}; };
ConstPtrType address(ConstRefType v) const noexcept { ConstPtrType address(ConstRefType v) const {
return address_of(v); return address_of(v);
}; };
SizeType max_size() const noexcept { return SizeType(~0) / sizeof(T); } SizeType max_size() const { return SizeType(~0) / sizeof(T); }
PtrType allocate(SizeType n, Allocator<void>::ConstPtrType = nullptr) noexcept { PtrType allocate(SizeType n, Allocator<void>::ConstPtrType = nullptr) {
return (PtrType) ::new uchar[n * sizeof(T)]; return (PtrType) ::new uchar[n * sizeof(T)];
} }
@ -601,13 +598,13 @@ namespace octa {
template<typename U> using Rebind = Allocator<U>; template<typename U> using Rebind = Allocator<U>;
ConstPtrType address(ConstRefType v) const noexcept { ConstPtrType address(ConstRefType v) const {
return address_of(v); return address_of(v);
}; };
SizeType max_size() const noexcept { return SizeType(~0) / sizeof(T); } SizeType max_size() const { return SizeType(~0) / sizeof(T); }
PtrType allocate(SizeType n, Allocator<void>::ConstPtrType = nullptr) noexcept { PtrType allocate(SizeType n, Allocator<void>::ConstPtrType = nullptr) {
return (PtrType) ::new uchar[n * sizeof(T)]; return (PtrType) ::new uchar[n * sizeof(T)];
} }
@ -622,12 +619,12 @@ namespace octa {
}; };
template<typename T, typename U> template<typename T, typename U>
bool operator==(const Allocator<T> &, const Allocator<U> &) noexcept { bool operator==(const Allocator<T> &, const Allocator<U> &) {
return true; return true;
} }
template<typename T, typename U> template<typename T, typename U>
bool operator!=(const Allocator<T> &, const Allocator<U> &) noexcept { bool operator!=(const Allocator<T> &, const Allocator<U> &) {
return false; return false;
} }
} }

View File

@ -26,7 +26,6 @@ namespace octa {
template<typename T> template<typename T>
struct __OctaRangeIterator { struct __OctaRangeIterator {
/* no need to mark noexcept as it's never instantiated directly */
__OctaRangeIterator(): p_range() {} __OctaRangeIterator(): p_range() {}
explicit __OctaRangeIterator(const T &range): p_range(range) {} explicit __OctaRangeIterator(const T &range): p_range(range) {}
__OctaRangeIterator &operator++() { __OctaRangeIterator &operator++() {
@ -52,14 +51,10 @@ namespace octa {
typedef V ValType; typedef V ValType;
typedef R RefType; typedef R RefType;
__OctaRangeIterator<B> begin() noexcept( __OctaRangeIterator<B> begin() {
IsNothrowCopyConstructible<B>::value
) {
return __OctaRangeIterator<B>((const B &)*this); return __OctaRangeIterator<B>((const B &)*this);
} }
__OctaRangeIterator<B> end() noexcept( __OctaRangeIterator<B> end() {
IsNothrowDefaultConstructible<B>::value
) {
return __OctaRangeIterator<B>(); return __OctaRangeIterator<B>();
} }
}; };
@ -83,106 +78,82 @@ namespace octa {
T p_range; T p_range;
public: public:
ReverseRange() noexcept(IsNothrowDefaultConstructible<T>::value): ReverseRange(): p_range() {}
p_range() {}
ReverseRange(const T &range) noexcept( ReverseRange(const T &range): p_range(range) {}
IsNothrowCopyConstructible<T>::value
): p_range(range) {}
ReverseRange(const ReverseRange &it) noexcept( ReverseRange(const ReverseRange &it): p_range(it.p_range) {}
IsNothrowCopyConstructible<T>::value
): p_range(it.p_range) {}
ReverseRange(ReverseRange &&it) noexcept( ReverseRange(ReverseRange &&it): p_range(move(it.p_range)) {}
IsNothrowMoveConstructible<T>::value
): p_range(move(it.p_range)) {}
ReverseRange &operator=(const ReverseRange &v) noexcept( ReverseRange &operator=(const ReverseRange &v) {
IsNothrowCopyAssignable<T>::value
) {
p_range = v.p_range; p_range = v.p_range;
return *this; return *this;
} }
ReverseRange &operator=(ReverseRange &&v) noexcept( ReverseRange &operator=(ReverseRange &&v) {
IsNothrowMoveAssignable<T>::value
) {
p_range = move(v.p_range); p_range = move(v.p_range);
return *this; return *this;
} }
ReverseRange &operator=(const T &v) noexcept( ReverseRange &operator=(const T &v) {
IsNothrowCopyAssignable<T>::value
) {
p_range = v; p_range = v;
return *this; return *this;
} }
ReverseRange &operator=(T &&v) noexcept( ReverseRange &operator=(T &&v) {
IsNothrowMoveAssignable<T>::value
) {
p_range = move(v); p_range = move(v);
return *this; return *this;
} }
bool empty() const noexcept(noexcept(p_range.empty())) { bool empty() const {
return p_range.empty(); return p_range.empty();
} }
r_size length() const noexcept(noexcept(p_range.length())) { r_size length() const {
return p_range.length(); return p_range.length();
} }
void pop_first() noexcept(noexcept(p_range.pop_last())) { void pop_first() {
p_range.pop_last(); p_range.pop_last();
} }
void pop_last() noexcept(noexcept(p_range.pop_first())) { void pop_last() {
p_range.pop_first(); p_range.pop_first();
} }
bool operator==(const ReverseRange &v) const noexcept( bool operator==(const ReverseRange &v) const {
noexcept(p_range == v.p_range)
) {
return p_range == v.p_range; return p_range == v.p_range;
} }
bool operator!=(const ReverseRange &v) const noexcept( bool operator!=(const ReverseRange &v) const {
noexcept(p_range != v.p_range)
) {
return p_range != v.p_range; return p_range != v.p_range;
} }
r_ref first() noexcept(noexcept(p_range.last())) { r_ref first() {
return p_range.last(); return p_range.last();
} }
r_ref first() const noexcept(noexcept(p_range.last())) { r_ref first() const {
return p_range.last(); return p_range.last();
} }
r_ref last() noexcept(noexcept(p_range.first())) { r_ref last() {
return p_range.first(); return p_range.first();
} }
r_ref last() const noexcept(noexcept(p_range.first())) { r_ref last() const {
return p_range.first(); return p_range.first();
} }
r_ref operator[](r_size i) noexcept(noexcept(p_range[0])) { r_ref operator[](r_size i) {
return p_range[length() - i - 1]; return p_range[length() - i - 1];
} }
r_ref operator[](r_size i) const noexcept(noexcept(p_range[0])) { r_ref operator[](r_size i) const {
return p_range[length() - i - 1]; return p_range[length() - i - 1];
} }
ReverseRange<T> slice(r_size start, r_size end) noexcept( ReverseRange<T> slice(r_size start, r_size end) {
noexcept(ReverseRange<T>(p_range.slice(0, 0)))
&& noexcept(p_range.length())
) {
r_size len = p_range.length(); r_size len = p_range.length();
return ReverseRange<T>(p_range.slice(len - end, len - start)); return ReverseRange<T>(p_range.slice(len - end, len - start));
} }
}; };
template<typename T> template<typename T>
ReverseRange<T> make_reverse_range(const T &it) noexcept( ReverseRange<T> make_reverse_range(const T &it) {
noexcept(ReverseRange<T>(it))
) {
return ReverseRange<T>(it); return ReverseRange<T>(it);
} }
@ -198,193 +169,170 @@ namespace octa {
T p_range; T p_range;
public: public:
MoveRange() noexcept(IsNothrowDefaultConstructible<T>::value): MoveRange(): p_range() {}
p_range() {}
MoveRange(const T &range) noexcept( MoveRange(const T &range): p_range(range) {}
IsNothrowCopyConstructible<T>::value
): p_range(range) {}
MoveRange(const MoveRange &it) noexcept( MoveRange(const MoveRange &it): p_range(it.p_range) {}
IsNothrowCopyConstructible<T>::value
): p_range(it.p_range) {}
MoveRange(MoveRange &&it) noexcept( MoveRange(MoveRange &&it): p_range(move(it.p_range)) {}
IsNothrowMoveConstructible<T>::value
): p_range(move(it.p_range)) {}
MoveRange &operator=(const MoveRange &v) noexcept( MoveRange &operator=(const MoveRange &v) {
IsNothrowCopyAssignable<T>::value
) {
p_range = v.p_range; p_range = v.p_range;
return *this; return *this;
} }
MoveRange &operator=(MoveRange &&v) noexcept( MoveRange &operator=(MoveRange &&v) {
IsNothrowMoveAssignable<T>::value
) {
p_range = move(v.p_range); p_range = move(v.p_range);
return *this; return *this;
} }
MoveRange &operator=(const T &v) noexcept( MoveRange &operator=(const T &v) {
IsNothrowCopyAssignable<T>::value
) {
p_range = v; p_range = v;
return *this; return *this;
} }
MoveRange &operator=(T &&v) noexcept( MoveRange &operator=(T &&v) {
IsNothrowMoveAssignable<T>::value
) {
p_range = move(v); p_range = move(v);
return *this; return *this;
} }
bool empty() const noexcept(noexcept(p_range.empty())) { bool empty() const {
return p_range.empty(); return p_range.empty();
} }
r_size length() const noexcept(noexcept(p_range.length())) { r_size length() const {
return p_range.length(); return p_range.length();
} }
void pop_first() noexcept(noexcept(p_range.pop_first())) { void pop_first() {
p_range.pop_first(); p_range.pop_first();
} }
void pop_last() noexcept(noexcept(p_range.pop_last())) { void pop_last() {
p_range.pop_last(); p_range.pop_last();
} }
bool operator==(const MoveRange &v) const noexcept( bool operator==(const MoveRange &v) const {
noexcept(p_range == v.p_range)
) {
return p_range == v.p_range; return p_range == v.p_range;
} }
bool operator!=(const MoveRange &v) const noexcept( bool operator!=(const MoveRange &v) const {
noexcept(p_range != v.p_range)
) {
return p_range != v.p_range; return p_range != v.p_range;
} }
r_ref first() noexcept(noexcept(p_range.first())) { r_ref first() {
return move(p_range.first()); return move(p_range.first());
} }
r_ref last() noexcept(noexcept(p_range.last())) { r_ref last() {
return move(p_range.last()); return move(p_range.last());
} }
r_ref operator[](r_size i) noexcept(noexcept(p_range[0])) { r_ref operator[](r_size i) {
return move(p_range[i]); return move(p_range[i]);
} }
MoveRange<T> slice(r_size start, r_size end) noexcept( MoveRange<T> slice(r_size start, r_size end) {
noexcept(MoveRange<T>(p_range.slice(start, end)))
) {
return MoveRange<T>(p_range.slice(start, end)); return MoveRange<T>(p_range.slice(start, end));
} }
void put(const r_val &v) noexcept(noexcept(p_range.put(v))) { void put(const r_val &v) {
p_range.put(v); p_range.put(v);
} }
void put(r_val &&v) noexcept(noexcept(p_range.put(move(v)))) { void put(r_val &&v) {
p_range.put(move(v)); p_range.put(move(v));
} }
}; };
template<typename T> template<typename T>
MoveRange<T> make_move_range(const T &it) noexcept( MoveRange<T> make_move_range(const T &it) {
noexcept(MoveRange<T>(it))
) {
return MoveRange<T>(it); return MoveRange<T>(it);
} }
template<typename T> template<typename T>
struct NumberRange: InputRange<NumberRange<T>, ForwardRangeTag, T> { struct NumberRange: InputRange<NumberRange<T>, ForwardRangeTag, T> {
NumberRange() noexcept: p_a(0), p_b(0), p_step(0) {} NumberRange(): p_a(0), p_b(0), p_step(0) {}
NumberRange(const NumberRange &it) noexcept: p_a(it.p_a), p_b(it.p_b), NumberRange(const NumberRange &it): p_a(it.p_a), p_b(it.p_b),
p_step(it.p_step) {} p_step(it.p_step) {}
NumberRange(T a, T b, T step = T(1)) noexcept: p_a(a), p_b(b), NumberRange(T a, T b, T step = T(1)): p_a(a), p_b(b),
p_step(step) {} p_step(step) {}
NumberRange(T v) noexcept: p_a(0), p_b(v), p_step(1) {} NumberRange(T v): p_a(0), p_b(v), p_step(1) {}
bool operator==(const NumberRange &v) const noexcept { bool operator==(const NumberRange &v) const {
return p_a == v.p_a && p_b == v.p_b && p_step == v.p_step; return p_a == v.p_a && p_b == v.p_b && p_step == v.p_step;
} }
bool operator!=(const NumberRange &v) const noexcept { bool operator!=(const NumberRange &v) const {
return p_a != v.p_a || p_b != v.p_b || p_step != v.p_step; return p_a != v.p_a || p_b != v.p_b || p_step != v.p_step;
} }
bool empty() const noexcept { return p_a * p_step >= p_b * p_step; } bool empty() const { return p_a * p_step >= p_b * p_step; }
void pop_first() noexcept { p_a += p_step; } void pop_first() { p_a += p_step; }
T &first() noexcept { return p_a; } T &first() { return p_a; }
private: private:
T p_a, p_b, p_step; T p_a, p_b, p_step;
}; };
template<typename T> template<typename T>
NumberRange<T> range(T a, T b, T step = T(1)) noexcept { NumberRange<T> range(T a, T b, T step = T(1)) {
return NumberRange<T>(a, b, step); return NumberRange<T>(a, b, step);
} }
template<typename T> template<typename T>
NumberRange<T> range(T v) noexcept { NumberRange<T> range(T v) {
return NumberRange<T>(v); return NumberRange<T>(v);
} }
template<typename T> template<typename T>
struct PointerRange: InputRange<PointerRange<T>, RandomAccessRangeTag, T> { struct PointerRange: InputRange<PointerRange<T>, RandomAccessRangeTag, T> {
PointerRange() noexcept: p_beg(nullptr), p_end(nullptr) {} PointerRange(): p_beg(nullptr), p_end(nullptr) {}
PointerRange(const PointerRange &v) noexcept: p_beg(v.p_beg), PointerRange(const PointerRange &v): p_beg(v.p_beg),
p_end(v.p_end) {} p_end(v.p_end) {}
PointerRange(T *beg, T *end) noexcept: p_beg(beg), p_end(end) {} PointerRange(T *beg, T *end): p_beg(beg), p_end(end) {}
PointerRange(T *beg, size_t n) noexcept: p_beg(beg), p_end(beg + n) {} PointerRange(T *beg, size_t n): p_beg(beg), p_end(beg + n) {}
PointerRange &operator=(const PointerRange &v) noexcept { PointerRange &operator=(const PointerRange &v) {
p_beg = v.p_beg; p_beg = v.p_beg;
p_end = v.p_end; p_end = v.p_end;
return *this; return *this;
} }
bool operator==(const PointerRange &v) const noexcept { bool operator==(const PointerRange &v) const {
return p_beg == v.p_beg && p_end == v.p_end; return p_beg == v.p_beg && p_end == v.p_end;
} }
bool operator!=(const PointerRange &v) const noexcept { bool operator!=(const PointerRange &v) const {
return p_beg != v.p_beg || p_end != v.p_end; return p_beg != v.p_beg || p_end != v.p_end;
} }
/* satisfy InputRange / ForwardRange */ /* satisfy InputRange / ForwardRange */
bool empty() const noexcept { return p_beg == nullptr; } bool empty() const { return p_beg == nullptr; }
void pop_first() noexcept { void pop_first() {
if (p_beg == nullptr) return; if (p_beg == nullptr) return;
if (++p_beg == p_end) p_beg = p_end = nullptr; if (++p_beg == p_end) p_beg = p_end = nullptr;
} }
T &first() noexcept { return *p_beg; } T &first() { return *p_beg; }
const T &first() const noexcept { return *p_beg; } const T &first() const { return *p_beg; }
/* satisfy BidirectionalRange */ /* satisfy BidirectionalRange */
void pop_last() noexcept { void pop_last() {
if (p_end-- == p_beg) { p_end = nullptr; return; } if (p_end-- == p_beg) { p_end = nullptr; return; }
if (p_end == p_beg) p_beg = p_end = nullptr; if (p_end == p_beg) p_beg = p_end = nullptr;
} }
T &last() noexcept { return *(p_end - 1); } T &last() { return *(p_end - 1); }
const T &last() const noexcept { return *(p_end - 1); } const T &last() const { return *(p_end - 1); }
/* satisfy RandomAccessRange */ /* satisfy RandomAccessRange */
size_t length() const noexcept { return p_end - p_beg; } size_t length() const { return p_end - p_beg; }
PointerRange slice(size_t start, size_t end) noexcept { PointerRange slice(size_t start, size_t end) {
return PointerRange(p_beg + start, p_beg + end); return PointerRange(p_beg + start, p_beg + end);
} }
T &operator[](size_t i) noexcept { return p_beg[i]; } T &operator[](size_t i) { return p_beg[i]; }
const T &operator[](size_t i) const noexcept { return p_beg[i]; } const T &operator[](size_t i) const { return p_beg[i]; }
/* satisfy OutputRange */ /* satisfy OutputRange */
void put(const T &v) noexcept(IsNothrowCopyAssignable<T>::value) { void put(const T &v) {
*(p_beg++) = v; *(p_beg++) = v;
} }
void put(T &&v) noexcept(IsNothrowMoveAssignable<T>::value) { void put(T &&v) {
*(p_beg++) = move(v); *(p_beg++) = move(v);
} }
@ -412,85 +360,62 @@ namespace octa {
r_size p_index; r_size p_index;
public: public:
EnumeratedRange() noexcept(IsNothrowDefaultConstructible<T>::value): EnumeratedRange(): p_range(), p_index(0) {}
p_range(), p_index(0) {}
EnumeratedRange(const T &range) noexcept( EnumeratedRange(const T &range): p_range(range), p_index(0) {}
IsNothrowCopyConstructible<T>::value
): p_range(range), p_index(0) {}
EnumeratedRange(const EnumeratedRange &it) noexcept( EnumeratedRange(const EnumeratedRange &it):
IsNothrowCopyConstructible<T>::value p_range(it.p_range), p_index(it.p_index) {}
): p_range(it.p_range), p_index(it.p_index) {}
EnumeratedRange(EnumeratedRange &&it) noexcept( EnumeratedRange(EnumeratedRange &&it):
IsNothrowMoveConstructible<T>::value p_range(move(it.p_range)), p_index(it.p_index) {}
): p_range(move(it.p_range)), p_index(it.p_index) {}
EnumeratedRange &operator=(const EnumeratedRange &v) noexcept( EnumeratedRange &operator=(const EnumeratedRange &v) {
IsNothrowCopyAssignable<T>::value
) {
p_range = v.p_range; p_range = v.p_range;
p_index = v.p_index; p_index = v.p_index;
return *this; return *this;
} }
EnumeratedRange &operator=(EnumeratedRange &&v) noexcept( EnumeratedRange &operator=(EnumeratedRange &&v) {
IsNothrowMoveAssignable<T>::value
) {
p_range = move(v.p_range); p_range = move(v.p_range);
p_index = v.p_index; p_index = v.p_index;
return *this; return *this;
} }
EnumeratedRange &operator=(const T &v) noexcept( EnumeratedRange &operator=(const T &v) {
IsNothrowCopyAssignable<T>::value
) {
p_range = v; p_range = v;
p_index = 0; p_index = 0;
return *this; return *this;
} }
EnumeratedRange &operator=(T &&v) noexcept( EnumeratedRange &operator=(T &&v) {
IsNothrowMoveAssignable<T>::value
) {
p_range = move(v); p_range = move(v);
p_index = 0; p_index = 0;
return *this; return *this;
} }
bool empty() const noexcept(noexcept(p_range.empty())) { bool empty() const {
return p_range.empty(); return p_range.empty();
} }
void pop_first() noexcept(noexcept(p_range.pop_last())) { void pop_first() {
++p_index; p_range.pop_first(); ++p_index; p_range.pop_first();
} }
EnumeratedValue<r_ref, r_size> first() noexcept( EnumeratedValue<r_ref, r_size> first() {
noexcept(p_range.first())
) {
return EnumeratedValue<r_ref, r_size> { p_index, p_range.first() }; return EnumeratedValue<r_ref, r_size> { p_index, p_range.first() };
} }
EnumeratedValue<r_ref, r_size> first() const noexcept( EnumeratedValue<r_ref, r_size> first() const {
noexcept(p_range.first())
) {
return EnumeratedValue<r_ref, r_size> { p_index, p_range.first() }; return EnumeratedValue<r_ref, r_size> { p_index, p_range.first() };
} }
bool operator==(const EnumeratedRange &v) const noexcept( bool operator==(const EnumeratedRange &v) const {
noexcept(p_range == v.p_range)
) {
return p_range == v.p_range; return p_range == v.p_range;
} }
bool operator!=(const EnumeratedRange &v) const noexcept( bool operator!=(const EnumeratedRange &v) const {
noexcept(p_range != v.p_range)
) {
return p_range != v.p_range; return p_range != v.p_range;
} }
}; };
template<typename T> template<typename T>
EnumeratedRange<T> enumerate(const T &it) noexcept( EnumeratedRange<T> enumerate(const T &it) {
noexcept(EnumeratedRange<T>(it))
) {
return EnumeratedRange<T>(it); return EnumeratedRange<T>(it);
} }
} }

View File

@ -325,7 +325,7 @@ namespace octa {
decltype(__OCTA_MOVE(T(__octa_declval<A>()...))), True decltype(__OCTA_MOVE(T(__octa_declval<A>()...))), True
>::Type __octa_is_ctible_test(T &&, A &&...); >::Type __octa_is_ctible_test(T &&, A &&...);
#undef __OCTA_MOVE //#undef __OCTA_MOVE
template<typename ...A> False __octa_is_ctible_test(__OctaAny, A &&...); template<typename ...A> False __octa_is_ctible_test(__OctaAny, A &&...);
@ -578,115 +578,6 @@ namespace octa {
__has_trivial_destructor(T) __has_trivial_destructor(T)
> {}; > {};
/* is nothrow constructible */
template<typename T, typename ...A>
struct IsNothrowConstructible: False {};
template<typename T>
struct IsNothrowConstructible<T>: IntegralConstant<bool,
__has_nothrow_constructor(T)
> {};
template<typename T>
struct IsNothrowConstructible<T, T &>: IntegralConstant<bool,
__has_nothrow_copy(T)
> {};
template<typename T>
struct IsNothrowConstructible<T, const T &>: IntegralConstant<bool,
__has_nothrow_copy(T)
> {};
template<typename T>
struct IsNothrowConstructible<T, T &&>: IntegralConstant<bool,
__has_nothrow_copy(T)
> {};
/* is nothrow default constructible */
template<typename T>
struct IsNothrowDefaultConstructible: IsNothrowConstructible<T> {};
/* is nothrow copy constructible */
template<typename T>
struct IsNothrowCopyConstructible: IsNothrowConstructible<T,
AddLvalueReference<const T>
> {};
/* is nothrow move constructible */
template<typename T>
struct IsNothrowMoveConstructible: IsNothrowConstructible<T,
AddRvalueReference<T>
> {};
/* is nothrow assignable */
template<typename T, typename ...A>
struct IsNothrowAssignable: False {};
template<typename T>
struct IsNothrowAssignable<T>: IntegralConstant<bool,
__has_nothrow_assign(T)
> {};
template<typename T>
struct IsNothrowAssignable<T, T &>: IntegralConstant<bool,
__has_nothrow_copy(T)
> {};
template<typename T>
struct IsNothrowAssignable<T, const T &>: IntegralConstant<bool,
__has_nothrow_copy(T)
> {};
template<typename T>
struct IsNothrowAssignable<T, T &&>: IntegralConstant<bool,
__has_nothrow_copy(T)
> {};
/* is nothrow copy assignable */
template<typename T>
struct IsNothrowCopyAssignable: IsNothrowAssignable<T,
AddLvalueReference<const T>
> {};
/* is nothrow move assignable */
template<typename T>
struct IsNothrowMoveAssignable: IsNothrowAssignable<T,
AddRvalueReference<T>
> {};
/* is nothrow destructible */
template<typename, bool> struct __OctaIsNothrowDtible;
template<typename T>
struct __OctaIsNothrowDtible<T, false>: False {};
template<typename T>
struct __OctaIsNothrowDtible<T, true>: IntegralConstant<bool,
(IsScalar<T>::value || noexcept(__octa_declval<T>().~T()))
> {};
template<typename T>
struct IsNothrowDestructible: __OctaIsNothrowDtible<T,
IsDestructible<T>::value
> {};
template<typename T, size_t N>
struct IsNothrowDestructible<T[N]>: IsNothrowDestructible<T> {};
template<typename T>
struct IsNothrowDestructible<T &>: IsNothrowDestructible<T> {};
template<typename T>
struct IsNothrowDestructible<T &&>: IsNothrowDestructible<T> {};
/* is base of */ /* is base of */
template<typename B, typename D> template<typename B, typename D>
@ -1127,11 +1018,11 @@ namespace octa {
template<typename ...T> struct __OctaCommonType; template<typename ...T> struct __OctaCommonType;
template<typename T> struct __OctaCommonType<T> { template<typename T> struct __OctaCommonType<T> {
typedef __OctaDecay<T> Type; typedef Decay<T> Type;
}; };
template<typename T, typename U> struct __OctaCommonType<T, U> { template<typename T, typename U> struct __OctaCommonType<T, U> {
typedef __OctaDecay<decltype(true ? __octa_declval<T>() typedef Decay<decltype(true ? __octa_declval<T>()
: __octa_declval<U>())> Type; : __octa_declval<U>())> Type;
}; };

View File

@ -14,22 +14,19 @@ namespace octa {
/* move */ /* move */
template<typename T> template<typename T>
static inline constexpr RemoveReference<T> && static inline constexpr RemoveReference<T> &&move(T &&v) {
move(T &&v) noexcept {
return static_cast<RemoveReference<T> &&>(v); return static_cast<RemoveReference<T> &&>(v);
} }
/* forward */ /* forward */
template<typename T> template<typename T>
static inline constexpr T && static inline constexpr T &&forward(RemoveReference<T> &v) {
forward(RemoveReference<T> &v) noexcept {
return static_cast<T &&>(v); return static_cast<T &&>(v);
} }
template<typename T> template<typename T>
static inline constexpr T && static inline constexpr T &&forward(RemoveReference<T> &&v) {
forward(RemoveReference<T> &&v) noexcept {
return static_cast<T &&>(v); return static_cast<T &&>(v);
} }
@ -39,18 +36,13 @@ namespace octa {
/* swap */ /* swap */
template<typename T> void swap(T &a, T &b) noexcept( template<typename T> void swap(T &a, T &b) {
IsNothrowMoveConstructible<T>::value
&& IsNothrowMoveAssignable<T>::value
) {
T c(move(a)); T c(move(a));
a = move(b); a = move(b);
b = move(c); b = move(c);
} }
template<typename T, size_t N> void swap(T (&a)[N], T (&b)[N]) noexcept( template<typename T, size_t N> void swap(T (&a)[N], T (&b)[N]) {
noexcept(swap(*a, *b))
) {
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
swap(a[i], b[i]); swap(a[i], b[i]);
} }
@ -63,64 +55,37 @@ namespace octa {
T first; T first;
U second; U second;
Pair() noexcept( Pair() = default;
IsNothrowDefaultConstructible<T>::value
&& IsNothrowDefaultConstructible<U>::value
) = default;
~Pair() = default; ~Pair() = default;
Pair(const Pair &) noexcept( Pair(const Pair &) = default;
IsNothrowCopyConstructible<T>::value Pair(Pair &&) = default;
&& IsNothrowCopyConstructible<U>::value
) = default;
Pair(Pair &&) noexcept(
IsNothrowMoveConstructible<T>::value
&& IsNothrowMoveConstructible<U>::value
) = default;
Pair(const T &x, const U &y) noexcept( Pair(const T &x, const U &y): first(x), second(y) {}
IsNothrowCopyConstructible<T>::value
&& IsNothrowCopyConstructible<U>::value
): first(x), second(y) {}
template<typename TT, typename UU> template<typename TT, typename UU>
Pair(TT &&x, UU &&y): first(forward<TT>(x)), second(forward<UU>(y)) {} Pair(TT &&x, UU &&y): first(forward<TT>(x)), second(forward<UU>(y)) {}
template<typename TT, typename UU> template<typename TT, typename UU>
Pair(const Pair<TT, UU> &v) noexcept( Pair(const Pair<TT, UU> &v): first(v.first), second(v.second) {}
IsNothrowCopyConstructible<T>::value
&& IsNothrowCopyConstructible<U>::value
): first(v.first), second(v.second) {}
template<typename TT, typename UU> template<typename TT, typename UU>
Pair(Pair<TT, UU> &&v) noexcept( Pair(Pair<TT, UU> &&v): first(move(v.first)), second(move(v.second)) {}
IsNothrowMoveConstructible<T>::value
&& IsNothrowMoveConstructible<U>::value
): first(move(v.first)), second(move(v.second)) {}
Pair &operator=(const Pair &v) noexcept( Pair &operator=(const Pair &v) {
IsNothrowCopyAssignable<T>::value
&& IsNothrowCopyAssignable<U>::value
) {
first = v.first; first = v.first;
second = v.second; second = v.second;
return *this; return *this;
} }
template<typename TT, typename UU> template<typename TT, typename UU>
Pair &operator=(const Pair<TT, UU> &v) noexcept( Pair &operator=(const Pair<TT, UU> &v) {
IsNothrowCopyAssignable<T>::value
&& IsNothrowCopyAssignable<U>::value
) {
first = v.first; first = v.first;
second = v.second; second = v.second;
return *this; return *this;
} }
Pair &operator=(Pair &&v) noexcept( Pair &operator=(Pair &&v) {
IsNothrowMoveAssignable<T>::value
&& IsNothrowMoveAssignable<U>::value
) {
first = move(v.first); first = move(v.first);
second = move(v.second); second = move(v.second);
return *this; return *this;
@ -133,17 +98,14 @@ namespace octa {
return *this; return *this;
} }
void swap(Pair &v) noexcept( void swap(Pair &v) {
noexcept(octa::swap(first, v.first))
&& noexcept(octa::swap(second, v.second))
) {
octa::swap(first, v.first); octa::swap(first, v.first);
octa::swap(second, v.second); octa::swap(second, v.second);
} }
}; };
template<typename T, typename U> template<typename T, typename U>
void swap(Pair<T, U> &a, Pair<T, U> &b) noexcept(noexcept(a.swap(b))) { void swap(Pair<T, U> &a, Pair<T, U> &b) {
a.swap(b); a.swap(b);
} }
} }

View File

@ -22,11 +22,7 @@ namespace octa {
T *p_buf; T *p_buf;
size_t p_len, p_cap; size_t p_len, p_cap;
void insert_base(size_t idx, size_t n) noexcept( void insert_base(size_t idx, size_t n) {
IsNothrowDestructible<T>::value
&& IsNothrowMoveConstructible<T>::value
&& IsNothrowMoveAssignable<T>::value
) {
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 (size_t i = p_len - 1; i > idx + n - 1; --i) { for (size_t i = p_len - 1; i > idx + n - 1; --i) {
@ -47,33 +43,25 @@ namespace octa {
typedef PointerRange< T> RangeType; typedef PointerRange< T> RangeType;
typedef PointerRange<const T> ConstRangeType; typedef PointerRange<const T> ConstRangeType;
Vector() noexcept: p_buf(nullptr), p_len(0), p_cap(0) {} Vector(): p_buf(nullptr), p_len(0), p_cap(0) {}
explicit Vector(size_t n, const T &val = T()) noexcept( explicit Vector(size_t n, const T &val = T()): Vector() {
IsNothrowCopyConstructible<T>::value
): Vector() {
p_buf = new uchar[n * sizeof(T)]; p_buf = new uchar[n * sizeof(T)];
p_len = p_cap = n; p_len = p_cap = n;
T *cur = p_buf, *last = p_buf + n; T *cur = p_buf, *last = p_buf + n;
while (cur != last) new (cur++) T(val); while (cur != last) new (cur++) T(val);
} }
Vector(const Vector &v) noexcept( Vector(const Vector &v): Vector() {
IsNothrowDestructible<T>::value
&& IsNothrowCopyConstructible<T>::value
): Vector() {
*this = v; *this = v;
} }
Vector(Vector &&v) noexcept: p_buf(v.p_buf), p_len(v.p_len), Vector(Vector &&v): p_buf(v.p_buf), p_len(v.p_len), p_cap(v.p_cap) {
p_cap(v.p_cap) {
v.p_buf = nullptr; v.p_buf = nullptr;
v.p_len = v.p_cap = 0; v.p_len = v.p_cap = 0;
} }
Vector(InitializerList<T> v) noexcept( Vector(InitializerList<T> v): Vector() {
IsNothrowCopyConstructible<T>::value
): Vector() {
size_t len = v.length(); size_t len = v.length();
const T *ptr = v.get(); const T *ptr = v.get();
reserve(len); reserve(len);
@ -82,14 +70,14 @@ namespace octa {
p_len = len; p_len = len;
} }
~Vector() noexcept(IsNothrowDestructible<T>::value) { ~Vector() {
clear(); clear();
delete[] (uchar *)p_buf; delete[] (uchar *)p_buf;
p_buf = nullptr; p_buf = nullptr;
p_cap = 0; p_cap = 0;
} }
void clear() noexcept(IsNothrowDestructible<T>::value) { void clear() {
if (p_len > 0 && !octa::IsPod<T>()) { if (p_len > 0 && !octa::IsPod<T>()) {
T *cur = p_buf, *last = p_buf + p_len; T *cur = p_buf, *last = p_buf + p_len;
while (cur != last) (*cur++).~T(); while (cur != last) (*cur++).~T();
@ -97,10 +85,7 @@ namespace octa {
p_len = 0; p_len = 0;
} }
Vector<T> &operator=(const Vector<T> &v) noexcept( Vector<T> &operator=(const Vector<T> &v) {
IsNothrowDestructible<T>::value
&& IsNothrowCopyConstructible<T>::value
) {
if (this == &v) return *this; if (this == &v) return *this;
clear(); clear();
reserve(v.p_cap); reserve(v.p_cap);
@ -117,9 +102,7 @@ namespace octa {
return *this; return *this;
} }
Vector<T> &operator=(Vector<T> &&v) noexcept( Vector<T> &operator=(Vector<T> &&v) {
IsNothrowDestructible<T>::value
) {
clear(); clear();
delete[] (uchar *)p_buf; delete[] (uchar *)p_buf;
p_len = v.p_len; p_len = v.p_len;
@ -128,10 +111,7 @@ namespace octa {
return *this; return *this;
} }
Vector<T> &operator=(InitializerList<T> il) noexcept( Vector<T> &operator=(InitializerList<T> il) {
IsNothrowDestructible<T>::value &&
IsNothrowCopyConstructible<T>::value
) {
clear(); clear();
size_t ilen = il.length(); size_t ilen = il.length();
reserve(ilen); reserve(ilen);
@ -147,11 +127,7 @@ namespace octa {
return *this; return *this;
} }
void resize(size_t n, const T &v = T()) noexcept( void resize(size_t n, const T &v = T()) {
IsNothrowDestructible<T>::value
&& IsNothrowMoveConstructible<T>::value
&& IsNothrowCopyConstructible<T>::value
) {
size_t len = p_len; size_t len = p_len;
reserve(n); reserve(n);
p_len = n; p_len = n;
@ -166,10 +142,7 @@ namespace octa {
} }
} }
void reserve(size_t n) noexcept( void reserve(size_t n) {
IsNothrowDestructible<T>::value
&& IsNothrowMoveConstructible<T>::value
) {
if (n <= p_len) { if (n <= p_len) {
if (n == p_len) return; if (n == p_len) return;
while (p_len > n) pop(); while (p_len > n) pop();
@ -198,25 +171,19 @@ namespace octa {
p_buf = tmp; p_buf = tmp;
} }
T &operator[](size_t i) noexcept { return p_buf[i]; } T &operator[](size_t i) { return p_buf[i]; }
const T &operator[](size_t i) const noexcept { return p_buf[i]; } const T &operator[](size_t i) const { return p_buf[i]; }
T &at(size_t i) noexcept { return p_buf[i]; } T &at(size_t i) { return p_buf[i]; }
const T &at(size_t i) const noexcept { return p_buf[i]; } const T &at(size_t i) const { return p_buf[i]; }
T &push(const T &v) noexcept( T &push(const T &v) {
noexcept(noexcept(reserve(0))) &&
IsNothrowCopyConstructible<T>::value
) {
if (p_len == p_cap) reserve(p_len + 1); if (p_len == p_cap) reserve(p_len + 1);
new (&p_buf[p_len]) T(v); new (&p_buf[p_len]) T(v);
return p_buf[p_len++]; return p_buf[p_len++];
} }
T &push() noexcept( T &push() {
noexcept(noexcept(reserve(0))) &&
IsNothrowDefaultConstructible<T>::value
) {
if (p_len == p_cap) reserve(p_len + 1); if (p_len == p_cap) reserve(p_len + 1);
new (&p_buf[p_len]) T; new (&p_buf[p_len]) T;
return p_buf[p_len++]; return p_buf[p_len++];
@ -229,7 +196,7 @@ namespace octa {
return p_buf[p_len++]; return p_buf[p_len++];
} }
void pop() noexcept(IsNothrowDestructible<T>::value) { void pop() {
if (!octa::IsPod<T>()) { if (!octa::IsPod<T>()) {
p_buf[--p_len].~T(); p_buf[--p_len].~T();
} else { } else {
@ -237,60 +204,46 @@ namespace octa {
} }
} }
T &first() noexcept { return p_buf[0]; } T &first() { return p_buf[0]; }
const T &first() const noexcept { return p_buf[0]; }; const T &first() const { return p_buf[0]; };
T &last() noexcept { return p_buf[p_len - 1]; } T &last() { return p_buf[p_len - 1]; }
const T &last() const noexcept { return p_buf[p_len - 1]; } const T &last() const { return p_buf[p_len - 1]; }
T *get() noexcept { return p_buf; } T *get() { return p_buf; }
const T *get() const noexcept { return p_buf; } const T *get() const { return p_buf; }
size_t length() const noexcept { return p_len; } size_t length() const { return p_len; }
size_t capacity() const noexcept { return p_cap; } size_t capacity() const { return p_cap; }
bool empty() const noexcept { return (p_len == 0); } bool empty() const { return (p_len == 0); }
bool in_range(size_t idx) noexcept { return idx < p_len; } bool in_range(size_t idx) { return idx < p_len; }
bool in_range(int idx) noexcept { return idx >= 0 && idx < p_len; } bool in_range(int idx) { return idx >= 0 && idx < p_len; }
bool in_range(const T *ptr) noexcept { bool in_range(const T *ptr) {
return ptr >= p_buf && ptr < &p_buf[p_len]; return ptr >= p_buf && ptr < &p_buf[p_len];
} }
T *disown() noexcept { T *disown() {
T *r = p_buf; T *r = p_buf;
p_buf = nullptr; p_buf = nullptr;
p_len = p_cap = 0; p_len = p_cap = 0;
return r; return r;
} }
T *insert(size_t idx, T &&v) noexcept( T *insert(size_t idx, T &&v) {
IsNothrowDestructible<T>::value
&& IsNothrowMoveConstructible<T>::value
&& IsNothrowMoveAssignable<T>::value
) {
insert_base(idx, 1); insert_base(idx, 1);
p_buf[idx] = move(v); p_buf[idx] = move(v);
return &p_buf[idx]; return &p_buf[idx];
} }
T *insert(size_t idx, const T &v) noexcept( T *insert(size_t idx, const T &v) {
IsNothrowDestructible<T>::value
&& IsNothrowMoveConstructible<T>::value
&& IsNothrowMoveAssignable<T>::value
&& IsNothrowCopyAssignable<T>::value
) {
insert_base(idx, 1); insert_base(idx, 1);
p_buf[idx] = v; p_buf[idx] = v;
return &p_buf[idx]; return &p_buf[idx];
} }
T *insert(size_t idx, size_t n, const T &v) noexcept( T *insert(size_t idx, size_t n, const T &v) {
IsNothrowDestructible<T>::value
&& IsNothrowMoveConstructible<T>::value
&& IsNothrowMoveAssignable<T>::value
&& IsNothrowCopyAssignable<T>::value
) {
insert_base(idx, n); insert_base(idx, n);
for (size_t i = 0; i < n; ++i) { for (size_t i = 0; i < n; ++i) {
p_buf[idx + i] = v; p_buf[idx + i] = v;
@ -299,14 +252,7 @@ namespace octa {
} }
template<typename U> template<typename U>
T *insert_range(size_t idx, U range) noexcept( T *insert_range(size_t idx, U range) {
IsNothrowDestructible<T>::value
&& IsNothrowMoveConstructible<T>::value
&& IsNothrowMoveAssignable<T>::value
&& noexcept(range.first())
&& noexcept(range.pop_first())
&& noexcept((*p_buf = range.first()))
) {
size_t len = range.length(); size_t len = range.length();
insert_base(idx, len); insert_base(idx, len);
for (size_t i = 0; i < len; ++i) { for (size_t i = 0; i < len; ++i) {
@ -316,20 +262,18 @@ namespace octa {
return &p_buf[idx]; return &p_buf[idx];
} }
T *insert(size_t idx, InitializerList<T> il) noexcept( T *insert(size_t idx, InitializerList<T> il) {
noexcept(declval<Vector<T>>().insert_range(idx, il.range()))
) {
return insert_range(idx, il.range()); return insert_range(idx, il.range());
} }
RangeType each() noexcept { RangeType each() {
return PointerRange<T>(p_buf, p_buf + p_len); return PointerRange<T>(p_buf, p_buf + p_len);
} }
ConstRangeType each() const noexcept { ConstRangeType each() const {
return PointerRange<const T>(p_buf, p_buf + p_len); return PointerRange<const T>(p_buf, p_buf + p_len);
} }
void swap(Vector &v) noexcept { void swap(Vector &v) {
swap(p_len, v.p_len); swap(p_len, v.p_len);
swap(p_cap, v.p_cap); swap(p_cap, v.p_cap);
swap(p_buf, v.p_buf); swap(p_buf, v.p_buf);
@ -337,7 +281,7 @@ namespace octa {
}; };
template<typename T> template<typename T>
void swap(Vector<T> &a, Vector<T> &b) noexcept { void swap(Vector<T> &a, Vector<T> &b) {
a.swap(b); a.swap(b);
} }
} }