noexcept the library
parent
f4b0691003
commit
1a2d606ae7
32
octa/array.h
32
octa/array.h
|
@ -23,32 +23,32 @@ namespace octa {
|
|||
typedef PointerRange< T> range;
|
||||
typedef PointerRange<const T> const_range;
|
||||
|
||||
T &operator[](size_t i) { return p_buf[i]; }
|
||||
const T &operator[](size_t i) const { return p_buf[i]; }
|
||||
T &operator[](size_t i) noexcept { return p_buf[i]; }
|
||||
const T &operator[](size_t i) const noexcept { return p_buf[i]; }
|
||||
|
||||
T &at(size_t i) { return p_buf[i]; }
|
||||
const T &at(size_t i) const { return p_buf[i]; }
|
||||
T &at(size_t i) noexcept { return p_buf[i]; }
|
||||
const T &at(size_t i) const noexcept { return p_buf[i]; }
|
||||
|
||||
T &first() { return p_buf[0]; }
|
||||
const T &first() const { return p_buf[0]; }
|
||||
T &first() noexcept { return p_buf[0]; }
|
||||
const T &first() const noexcept { return p_buf[0]; }
|
||||
|
||||
T &last() { return p_buf[N - 1]; }
|
||||
const T &last() const { return p_buf[N - 1]; }
|
||||
T &last() noexcept { return p_buf[N - 1]; }
|
||||
const T &last() const noexcept { return p_buf[N - 1]; }
|
||||
|
||||
bool empty() const { return (N > 0); }
|
||||
size_t length() const { return N; }
|
||||
bool empty() const noexcept { return (N > 0); }
|
||||
size_t length() const noexcept { return N; }
|
||||
|
||||
T *get() { return p_buf; }
|
||||
const T *get() const { return p_buf; }
|
||||
T *get() noexcept { return p_buf; }
|
||||
const T *get() const noexcept { return p_buf; }
|
||||
|
||||
void swap(Array &v) {
|
||||
void swap(Array &v) noexcept {
|
||||
swap(p_buf, v.p_buf);
|
||||
}
|
||||
|
||||
range each() {
|
||||
range each() noexcept {
|
||||
return PointerRange<T>(p_buf, p_buf + N);
|
||||
}
|
||||
const_range each() const {
|
||||
const_range each() const noexcept {
|
||||
return PointerRange<const T>(p_buf, p_buf + N);
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ namespace octa {
|
|||
};
|
||||
|
||||
template<typename T, size_t N>
|
||||
void swap(Array<T, N> &a, Array<T, N> &b) {
|
||||
void swap(Array<T, N> &a, Array<T, N> &b) noexcept {
|
||||
a.swap(b);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,13 +43,13 @@ namespace octa {
|
|||
#undef __OCTA_DEFINE_BINARY_OP
|
||||
|
||||
template<typename T> struct LogicalNot {
|
||||
bool operator()(const T &x) const { return !x; }
|
||||
bool operator()(const T &x) const noexcept(noexcept(!x)) { return !x; }
|
||||
typedef T argument_type;
|
||||
typedef bool result_type;
|
||||
};
|
||||
|
||||
template<typename T> struct Negate {
|
||||
bool operator()(const T &x) const { return -x; }
|
||||
bool operator()(const T &x) const noexcept(noexcept(-x)) { return -x; }
|
||||
typedef T argument_type;
|
||||
typedef T result_type;
|
||||
};
|
||||
|
@ -59,7 +59,9 @@ namespace octa {
|
|||
typedef typename T::second_argument_type second_argument_type;
|
||||
typedef bool result_type;
|
||||
|
||||
explicit BinaryNegate(const T &f): p_fn(f) {}
|
||||
explicit BinaryNegate(const T &f)
|
||||
noexcept(IsNothrowCopyConstructible<T>::value): p_fn(f) {}
|
||||
|
||||
bool operator()(const first_argument_type &x,
|
||||
const second_argument_type &y)
|
||||
noexcept(noexcept(p_fn(x, y))) {
|
||||
|
@ -73,7 +75,8 @@ namespace octa {
|
|||
typedef typename T::argument_type argument_type;
|
||||
typedef bool result_type;
|
||||
|
||||
explicit UnaryNegate(const T &f) noexcept: p_fn(f) {}
|
||||
explicit UnaryNegate(const T &f)
|
||||
noexcept(IsNothrowCopyConstructible<T>::value): p_fn(f) {}
|
||||
bool operator()(const argument_type &x) noexcept(noexcept(p_fn(x))) {
|
||||
return !p_fn(x);
|
||||
}
|
||||
|
@ -82,12 +85,12 @@ namespace octa {
|
|||
};
|
||||
|
||||
template<typename T> UnaryNegate<T> not1(const T &fn)
|
||||
noexcept(noexcept(UnaryNegate<T>(fn))) {
|
||||
noexcept(IsNothrowCopyConstructible<UnaryNegate<T>>::value) {
|
||||
return UnaryNegate<T>(fn);
|
||||
}
|
||||
|
||||
template<typename T> BinaryNegate<T> not2(const T &fn)
|
||||
noexcept(noexcept(BinaryNegate<T>(fn))) {
|
||||
noexcept(IsNothrowCopyConstructible<BinaryNegate<T>>::value) {
|
||||
return BinaryNegate<T>(fn);
|
||||
}
|
||||
|
||||
|
@ -97,7 +100,7 @@ namespace octa {
|
|||
struct ReferenceWrapper {
|
||||
typedef T type;
|
||||
|
||||
ReferenceWrapper(T &v): p_ptr(address_of(v)) {}
|
||||
ReferenceWrapper(T &v) noexcept: p_ptr(address_of(v)) {}
|
||||
ReferenceWrapper(const ReferenceWrapper &) = default;
|
||||
ReferenceWrapper(T &&) = delete;
|
||||
|
||||
|
@ -216,15 +219,15 @@ namespace octa {
|
|||
new (&get_ref(s)) T(forward<T>(v));
|
||||
}
|
||||
|
||||
static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) {
|
||||
static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) noexcept {
|
||||
new (&get_ref(lhs)) T(move(get_ref(rhs)));
|
||||
}
|
||||
|
||||
static void destroy_f(__OctaFunctorData &s) {
|
||||
static void destroy_f(__OctaFunctorData &s) noexcept {
|
||||
get_ref(s).~T();
|
||||
}
|
||||
|
||||
static T &get_ref(const __OctaFunctorData &s) {
|
||||
static T &get_ref(const __OctaFunctorData &s) noexcept {
|
||||
return (T &)s;
|
||||
}
|
||||
};
|
||||
|
@ -240,27 +243,27 @@ namespace octa {
|
|||
new (&get_ptr_ref(s)) T *(new T(forward<T>(v)));
|
||||
}
|
||||
|
||||
static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) {
|
||||
static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) noexcept {
|
||||
new (&get_ptr_ref(lhs)) T *(get_ptr_ref(rhs));
|
||||
get_ptr_ref(rhs) = nullptr;
|
||||
}
|
||||
|
||||
static void destroy_f(__OctaFunctorData &s) {
|
||||
static void destroy_f(__OctaFunctorData &s) noexcept {
|
||||
T *&ptr = get_ptr_ref(s);
|
||||
if (!ptr) return;
|
||||
delete ptr;
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
static T &get_ref(const __OctaFunctorData &s) {
|
||||
static T &get_ref(const __OctaFunctorData &s) noexcept {
|
||||
return *get_ptr_ref(s);
|
||||
}
|
||||
|
||||
static T *&get_ptr_ref(__OctaFunctorData &s) {
|
||||
static T *&get_ptr_ref(__OctaFunctorData &s) noexcept {
|
||||
return (T *&)s;
|
||||
}
|
||||
|
||||
static T *&get_ptr_ref(const __OctaFunctorData &s) {
|
||||
static T *&get_ptr_ref(const __OctaFunctorData &s) noexcept {
|
||||
return (T *&)s;
|
||||
}
|
||||
};
|
||||
|
@ -345,17 +348,17 @@ namespace octa {
|
|||
Function( ) noexcept { initialize_empty(); }
|
||||
Function(nullptr_t) noexcept { initialize_empty(); }
|
||||
|
||||
Function(Function &&f) {
|
||||
Function(Function &&f) noexcept {
|
||||
initialize_empty();
|
||||
swap(f);
|
||||
}
|
||||
|
||||
Function(const Function &f): p_call(f.p_call) {
|
||||
Function(const Function &f) noexcept: p_call(f.p_call) {
|
||||
f.p_stor.manager->call_copy(p_stor, f.p_stor);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Function(T f) {
|
||||
Function(T f) noexcept(__OctaFunctorInPlace<T>::value) {
|
||||
if (func_is_null(f)) {
|
||||
initialize_empty();
|
||||
return;
|
||||
|
@ -367,13 +370,13 @@ namespace octa {
|
|||
p_stor.manager->call_destroy(p_stor);
|
||||
}
|
||||
|
||||
Function &operator=(Function &&f) {
|
||||
Function &operator=(Function &&f) noexcept {
|
||||
p_stor.manager->call_destroy(p_stor);
|
||||
swap(f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Function &operator=(const Function &f) {
|
||||
Function &operator=(const Function &f) noexcept {
|
||||
p_stor.manager->call_destroy(p_stor);
|
||||
f.p_stor.manager->call_copy(p_stor, f.p_stor);
|
||||
return *this;
|
||||
|
@ -384,7 +387,7 @@ namespace octa {
|
|||
}
|
||||
|
||||
template<typename F>
|
||||
void assign(F &&f) {
|
||||
void assign(F &&f) noexcept(__OctaFunctorInPlace<F>::value) {
|
||||
Function(forward<F>(f)).swap(*this);
|
||||
}
|
||||
|
||||
|
@ -409,7 +412,7 @@ namespace octa {
|
|||
__OctaFunctorDataManager<T>::store_f(p_stor.data, forward<T>(f));
|
||||
}
|
||||
|
||||
void initialize_empty() {
|
||||
void initialize_empty() noexcept {
|
||||
typedef R(*emptyf)(A...);
|
||||
p_call = nullptr;
|
||||
p_stor.manager = &__octa_get_default_fm<emptyf>();
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace std {
|
|||
const T *p_buf;
|
||||
size_t p_len;
|
||||
|
||||
initializer_list(const T *v, size_t n): p_buf(v), p_len(n) {}
|
||||
initializer_list(const T *v, size_t n) noexcept: p_buf(v), p_len(n) {}
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
|
@ -27,13 +27,13 @@ namespace std {
|
|||
typedef T *pointer;
|
||||
typedef const T *const_pointer;
|
||||
|
||||
initializer_list(): p_buf(nullptr), p_len(0) {}
|
||||
initializer_list() noexcept: p_buf(nullptr), p_len(0) {}
|
||||
|
||||
size_t length() const { return p_len; }
|
||||
size_t length() const noexcept { return p_len; }
|
||||
|
||||
const T *get() const { return p_buf; }
|
||||
const T *get() const noexcept { return p_buf; }
|
||||
|
||||
octa::PointerRange<const T> range() {
|
||||
octa::PointerRange<const T> range() noexcept {
|
||||
return octa::PointerRange<const T>(p_buf, p_len);
|
||||
}
|
||||
};
|
||||
|
|
298
octa/range.h
298
octa/range.h
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "octa/types.h"
|
||||
#include "octa/utility.h"
|
||||
#include "octa/type_traits.h"
|
||||
|
||||
namespace octa {
|
||||
struct InputRangeTag {};
|
||||
|
@ -28,6 +29,7 @@ namespace octa {
|
|||
|
||||
template<typename T>
|
||||
struct __OctaRangeIterator {
|
||||
/* no need to mark noexcept as it's never instantiated directly */
|
||||
__OctaRangeIterator(): p_range() {}
|
||||
explicit __OctaRangeIterator(const T &range): p_range(range) {}
|
||||
__OctaRangeIterator &operator++() {
|
||||
|
@ -53,10 +55,12 @@ namespace octa {
|
|||
typedef V value_type;
|
||||
typedef R reference;
|
||||
|
||||
__OctaRangeIterator<B> begin() {
|
||||
__OctaRangeIterator<B> begin()
|
||||
noexcept(IsNothrowCopyConstructible<B>::value) {
|
||||
return __OctaRangeIterator<B>((const B &)*this);
|
||||
}
|
||||
__OctaRangeIterator<B> end() {
|
||||
__OctaRangeIterator<B> end()
|
||||
noexcept(IsNothrowDefaultConstructible<B>::value) {
|
||||
return __OctaRangeIterator<B>();
|
||||
}
|
||||
};
|
||||
|
@ -80,67 +84,99 @@ namespace octa {
|
|||
typedef typename RangeTraits<T>::reference r_ref;
|
||||
typedef typename RangeTraits<T>::size_type r_size;
|
||||
|
||||
public:
|
||||
ReverseRange(): p_range() {}
|
||||
ReverseRange(const T &range): p_range(range) {}
|
||||
ReverseRange(const ReverseRange &it): p_range(it.p_range) {}
|
||||
ReverseRange(ReverseRange &&it): p_range(move(it.p_range)) {}
|
||||
T p_range;
|
||||
|
||||
ReverseRange &operator=(const ReverseRange &v) {
|
||||
public:
|
||||
ReverseRange()
|
||||
noexcept(IsNothrowDefaultConstructible<T>::value): p_range() {}
|
||||
|
||||
ReverseRange(const T &range)
|
||||
noexcept(IsNothrowCopyConstructible<T>::value): p_range(range) {}
|
||||
|
||||
ReverseRange(const ReverseRange &it)
|
||||
noexcept(IsNothrowCopyConstructible<T>::value): p_range(it.p_range) {}
|
||||
|
||||
ReverseRange(ReverseRange &&it)
|
||||
noexcept(IsNothrowMoveConstructible<T>::value):
|
||||
p_range(move(it.p_range)) {}
|
||||
|
||||
ReverseRange &operator=(const ReverseRange &v)
|
||||
noexcept(IsNothrowCopyAssignable<T>::value) {
|
||||
p_range = v.p_range;
|
||||
return *this;
|
||||
}
|
||||
ReverseRange &operator=(ReverseRange &&v) {
|
||||
ReverseRange &operator=(ReverseRange &&v)
|
||||
noexcept(IsNothrowMoveAssignable<T>::value) {
|
||||
p_range = move(v.p_range);
|
||||
return *this;
|
||||
}
|
||||
ReverseRange &operator=(const T &v) {
|
||||
ReverseRange &operator=(const T &v)
|
||||
noexcept(IsNothrowCopyAssignable<T>::value) {
|
||||
p_range = v;
|
||||
return *this;
|
||||
}
|
||||
ReverseRange &operator=(T &&v) {
|
||||
p_range = forward<T>(v);
|
||||
ReverseRange &operator=(T &&v)
|
||||
noexcept(IsNothrowMoveAssignable<T>::value) {
|
||||
p_range = move(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const { return p_range.empty(); }
|
||||
bool empty() const noexcept(noexcept(p_range.empty())) {
|
||||
return p_range.empty();
|
||||
}
|
||||
|
||||
r_size length() const { return p_range.length(); }
|
||||
r_size length() const noexcept(noexcept(p_range.length())) {
|
||||
return p_range.length();
|
||||
}
|
||||
|
||||
void pop_first() { p_range.pop_last (); }
|
||||
void pop_last () { p_range.pop_first(); }
|
||||
void pop_first() noexcept(noexcept(p_range.pop_last())) {
|
||||
p_range.pop_last();
|
||||
}
|
||||
void pop_last() noexcept(noexcept(p_range.pop_first())) {
|
||||
p_range.pop_first();
|
||||
}
|
||||
|
||||
bool operator==(const ReverseRange &v) const {
|
||||
bool operator==(const ReverseRange &v) const
|
||||
noexcept(noexcept(p_range == v.p_range)) {
|
||||
return p_range == v.p_range;
|
||||
}
|
||||
bool operator!=(const ReverseRange &v) const {
|
||||
bool operator!=(const ReverseRange &v) const
|
||||
noexcept(noexcept(p_range != v.p_range)) {
|
||||
return p_range != v.p_range;
|
||||
}
|
||||
|
||||
r_ref first() { return p_range.last(); }
|
||||
r_ref first() const { return p_range.last(); }
|
||||
r_ref first() noexcept(noexcept(p_range.last())) {
|
||||
return p_range.last();
|
||||
}
|
||||
r_ref first() const noexcept(noexcept(p_range.last())) {
|
||||
return p_range.last();
|
||||
}
|
||||
|
||||
r_ref last() { return p_range.first(); }
|
||||
r_ref last() const { return p_range.first(); }
|
||||
r_ref last() noexcept(noexcept(p_range.first())) {
|
||||
return p_range.first();
|
||||
}
|
||||
r_ref last() const noexcept(noexcept(p_range.first())) {
|
||||
return p_range.first();
|
||||
}
|
||||
|
||||
r_ref operator[](r_size i) {
|
||||
r_ref operator[](r_size i) noexcept(noexcept(p_range[0])) {
|
||||
return p_range[length() - i - 1];
|
||||
}
|
||||
r_ref operator[](r_size i) const {
|
||||
r_ref operator[](r_size i) const noexcept(noexcept(p_range[0])) {
|
||||
return p_range[length() - i - 1];
|
||||
}
|
||||
|
||||
ReverseRange<T> slice(r_size start, r_size end) {
|
||||
ReverseRange<T> slice(r_size start, r_size end)
|
||||
noexcept(noexcept(ReverseRange<T>(p_range.slice(0, 0)))
|
||||
&& noexcept(p_range.length())) {
|
||||
r_size len = p_range.length();
|
||||
return ReverseRange<T>(p_range.slice(len - end, len - start));
|
||||
}
|
||||
|
||||
private:
|
||||
T p_range;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
ReverseRange<T> make_reverse_range(const T &it) {
|
||||
ReverseRange<T> make_reverse_range(const T &it)
|
||||
noexcept(noexcept(ReverseRange<T>(it))) {
|
||||
return ReverseRange<T>(it);
|
||||
}
|
||||
|
||||
|
@ -156,143 +192,176 @@ namespace octa {
|
|||
typedef typename RangeTraits<T>::value_type &&r_ref;
|
||||
typedef typename RangeTraits<T>::size_type r_size;
|
||||
|
||||
public:
|
||||
MoveRange(): p_range() {}
|
||||
MoveRange(const T &range): p_range(range) {}
|
||||
MoveRange(const MoveRange &it): p_range(it.p_range) {}
|
||||
MoveRange(MoveRange &&it): p_range(move(it.p_range)) {}
|
||||
T p_range;
|
||||
|
||||
MoveRange &operator=(const MoveRange &v) {
|
||||
public:
|
||||
MoveRange()
|
||||
noexcept(IsNothrowDefaultConstructible<T>::value): p_range() {}
|
||||
|
||||
MoveRange(const T &range)
|
||||
noexcept(IsNothrowCopyConstructible<T>::value): p_range(range) {}
|
||||
|
||||
MoveRange(const MoveRange &it)
|
||||
noexcept(IsNothrowCopyConstructible<T>::value): p_range(it.p_range) {}
|
||||
|
||||
MoveRange(MoveRange &&it)
|
||||
noexcept(IsNothrowMoveConstructible<T>::value):
|
||||
p_range(move(it.p_range)) {}
|
||||
|
||||
MoveRange &operator=(const MoveRange &v)
|
||||
noexcept(IsNothrowCopyAssignable<T>::value) {
|
||||
p_range = v.p_range;
|
||||
return *this;
|
||||
}
|
||||
MoveRange &operator=(MoveRange &&v) {
|
||||
MoveRange &operator=(MoveRange &&v)
|
||||
noexcept(IsNothrowMoveAssignable<T>::value) {
|
||||
p_range = move(v.p_range);
|
||||
return *this;
|
||||
}
|
||||
MoveRange &operator=(const T &v) {
|
||||
MoveRange &operator=(const T &v)
|
||||
noexcept(IsNothrowCopyAssignable<T>::value) {
|
||||
p_range = v;
|
||||
return *this;
|
||||
}
|
||||
MoveRange &operator=(T &&v) {
|
||||
p_range = forward<T>(v);
|
||||
MoveRange &operator=(T &&v)
|
||||
noexcept(IsNothrowMoveAssignable<T>::value) {
|
||||
p_range = move(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty () const { return p_range.empty (); }
|
||||
r_size length() const { return p_range.length(); }
|
||||
bool empty() const noexcept(noexcept(p_range.empty())) {
|
||||
return p_range.empty();
|
||||
}
|
||||
r_size length() const noexcept(noexcept(p_range.length())) {
|
||||
return p_range.length();
|
||||
}
|
||||
|
||||
void pop_first() { p_range.pop_first(); }
|
||||
void pop_last () { p_range.pop_last (); }
|
||||
void pop_first() noexcept(noexcept(p_range.pop_first())) {
|
||||
p_range.pop_first();
|
||||
}
|
||||
void pop_last() noexcept(noexcept(p_range.pop_last())) {
|
||||
p_range.pop_last();
|
||||
}
|
||||
|
||||
bool operator==(const MoveRange &v) const {
|
||||
bool operator==(const MoveRange &v) const
|
||||
noexcept(noexcept(p_range == v.p_range)) {
|
||||
return p_range == v.p_range;
|
||||
}
|
||||
bool operator!=(const MoveRange &v) const {
|
||||
bool operator!=(const MoveRange &v) const
|
||||
noexcept(noexcept(p_range != v.p_range)) {
|
||||
return p_range != v.p_range;
|
||||
}
|
||||
|
||||
r_ref first() { return move(p_range.first()); }
|
||||
r_ref last () { return move(p_range.last()); }
|
||||
r_ref first() noexcept(noexcept(p_range.first())) {
|
||||
return move(p_range.first());
|
||||
}
|
||||
r_ref last() noexcept(noexcept(p_range.last())) {
|
||||
return move(p_range.last());
|
||||
}
|
||||
|
||||
r_ref operator[](r_size i) {
|
||||
r_ref operator[](r_size i) noexcept(noexcept(p_range[0])) {
|
||||
return move(p_range[i]);
|
||||
}
|
||||
|
||||
MoveRange<T> slice(r_size start, r_size end) {
|
||||
MoveRange<T> slice(r_size start, r_size end)
|
||||
noexcept(noexcept(MoveRange<T>(p_range.slice(start, end)))) {
|
||||
return MoveRange<T>(p_range.slice(start, end));
|
||||
}
|
||||
|
||||
void put(r_val &v) { p_range.put(v); }
|
||||
|
||||
private:
|
||||
T p_range;
|
||||
void put(r_val &v) noexcept(noexcept(p_range.put(v))) {
|
||||
p_range.put(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
MoveRange<T> make_move_range(const T &it) {
|
||||
MoveRange<T> make_move_range(const T &it)
|
||||
noexcept(noexcept(MoveRange<T>(it))) {
|
||||
return MoveRange<T>(it);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct NumberRange: InputRange<NumberRange<T>, ForwardRangeTag, T> {
|
||||
NumberRange(): p_a(0), p_b(0), p_step(0) {}
|
||||
NumberRange(const NumberRange &it): p_a(it.p_a), p_b(it.p_b),
|
||||
NumberRange() noexcept: p_a(0), p_b(0), p_step(0) {}
|
||||
NumberRange(const NumberRange &it) noexcept: p_a(it.p_a), p_b(it.p_b),
|
||||
p_step(it.p_step) {}
|
||||
NumberRange(T a, T b, T step = 1): p_a(a), p_b(b), p_step(step) {}
|
||||
NumberRange(T v): p_a(0), p_b(v), p_step(1) {}
|
||||
NumberRange(T a, T b, T step = 1) noexcept: p_a(a), p_b(b),
|
||||
p_step(step) {}
|
||||
NumberRange(T v) noexcept: p_a(0), p_b(v), p_step(1) {}
|
||||
|
||||
bool operator==(const NumberRange &v) const {
|
||||
bool operator==(const NumberRange &v) const noexcept {
|
||||
return p_a == v.p_a && p_b == v.p_b && p_step == v.p_step;
|
||||
}
|
||||
bool operator!=(const NumberRange &v) const {
|
||||
bool operator!=(const NumberRange &v) const noexcept {
|
||||
return p_a != v.p_a || p_b != v.p_b || p_step != v.p_step;
|
||||
}
|
||||
|
||||
bool empty() const { return p_a * p_step >= p_b * p_step; }
|
||||
void pop_first() { p_a += p_step; }
|
||||
T &first() { return p_a; }
|
||||
bool empty() const noexcept { return p_a * p_step >= p_b * p_step; }
|
||||
void pop_first() noexcept { p_a += p_step; }
|
||||
T &first() noexcept { return p_a; }
|
||||
|
||||
private:
|
||||
T p_a, p_b, p_step;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
NumberRange<T> range(T a, T b, T step = 1) {
|
||||
NumberRange<T> range(T a, T b, T step = 1) noexcept {
|
||||
return NumberRange<T>(a, b, step);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NumberRange<T> range(T v) {
|
||||
NumberRange<T> range(T v) noexcept {
|
||||
return NumberRange<T>(v);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct PointerRange: InputRange<PointerRange<T>, RandomAccessRangeTag, T> {
|
||||
PointerRange(): p_beg(nullptr), p_end(nullptr) {}
|
||||
PointerRange(const PointerRange &v): p_beg(v.p_beg), p_end(v.p_end) {}
|
||||
PointerRange(T *beg, T *end): p_beg(beg), p_end(end) {}
|
||||
PointerRange(T *beg, size_t n): p_beg(beg), p_end(beg + n) {}
|
||||
PointerRange() noexcept: p_beg(nullptr), p_end(nullptr) {}
|
||||
PointerRange(const PointerRange &v) noexcept: p_beg(v.p_beg),
|
||||
p_end(v.p_end) {}
|
||||
PointerRange(T *beg, T *end) noexcept: p_beg(beg), p_end(end) {}
|
||||
PointerRange(T *beg, size_t n) noexcept: p_beg(beg), p_end(beg + n) {}
|
||||
|
||||
bool operator==(const PointerRange &v) const {
|
||||
bool operator==(const PointerRange &v) const noexcept {
|
||||
return p_beg == v.p_beg && p_end == v.p_end;
|
||||
}
|
||||
bool operator!=(const PointerRange &v) const {
|
||||
bool operator!=(const PointerRange &v) const noexcept {
|
||||
return p_beg != v.p_beg || p_end != v.p_end;
|
||||
}
|
||||
|
||||
/* satisfy InputRange / ForwardRange */
|
||||
bool empty() const { return p_beg == nullptr; }
|
||||
bool empty() const noexcept { return p_beg == nullptr; }
|
||||
|
||||
void pop_first() {
|
||||
void pop_first() noexcept {
|
||||
if (p_beg == nullptr) return;
|
||||
if (++p_beg == p_end) p_beg = p_end = nullptr;
|
||||
}
|
||||
|
||||
T &first() { return *p_beg; }
|
||||
const T &first() const { return *p_beg; }
|
||||
T &first() noexcept { return *p_beg; }
|
||||
const T &first() const noexcept { return *p_beg; }
|
||||
|
||||
/* satisfy BidirectionalRange */
|
||||
void pop_last() {
|
||||
void pop_last() noexcept {
|
||||
if (p_end-- == p_beg) { p_end = nullptr; return; }
|
||||
if (p_end == p_beg) p_beg = p_end = nullptr;
|
||||
}
|
||||
|
||||
T &last() { return *(p_end - 1); }
|
||||
const T &last() const { return *(p_end - 1); }
|
||||
T &last() noexcept { return *(p_end - 1); }
|
||||
const T &last() const noexcept { return *(p_end - 1); }
|
||||
|
||||
/* satisfy RandomAccessRange */
|
||||
size_t length() const { return p_end - p_beg; }
|
||||
size_t length() const noexcept { return p_end - p_beg; }
|
||||
|
||||
PointerRange slice(size_t start, size_t end) {
|
||||
PointerRange slice(size_t start, size_t end) noexcept {
|
||||
return PointerRange(p_beg + start, p_beg + end);
|
||||
}
|
||||
|
||||
T &operator[](size_t i) { return p_beg[i]; }
|
||||
const T &operator[](size_t i) const { return p_beg[i]; }
|
||||
T &operator[](size_t i) noexcept { return p_beg[i]; }
|
||||
const T &operator[](size_t i) const noexcept { return p_beg[i]; }
|
||||
|
||||
/* satisfy OutputRange */
|
||||
void put(const T &v) { *(p_beg++) = v; }
|
||||
void put(const T &v) noexcept(IsNothrowCopyAssignable<T>::value) {
|
||||
*(p_beg++) = v;
|
||||
}
|
||||
|
||||
private:
|
||||
T *p_beg, *p_end;
|
||||
|
@ -315,60 +384,81 @@ namespace octa {
|
|||
typedef typename RangeTraits<T>::reference r_ref;
|
||||
typedef typename RangeTraits<T>::size_type r_size;
|
||||
|
||||
T p_range;
|
||||
r_size p_index;
|
||||
|
||||
public:
|
||||
EnumeratedRange(): p_range(), p_index(0) {}
|
||||
EnumeratedRange(const T &range): p_range(range), p_index(0) {}
|
||||
EnumeratedRange(const EnumeratedRange &it): p_range(it.p_range),
|
||||
p_index(it.p_index) {}
|
||||
EnumeratedRange(EnumeratedRange &&it): p_range(move(it.p_range)),
|
||||
EnumeratedRange()
|
||||
noexcept(IsNothrowDefaultConstructible<T>::value): p_range(),
|
||||
p_index(0) {}
|
||||
|
||||
EnumeratedRange(const T &range)
|
||||
noexcept(IsNothrowCopyConstructible<T>::value): p_range(range),
|
||||
p_index(0) {}
|
||||
|
||||
EnumeratedRange(const EnumeratedRange &it)
|
||||
noexcept(IsNothrowCopyConstructible<T>::value): p_range(it.p_range),
|
||||
p_index(it.p_index) {}
|
||||
|
||||
EnumeratedRange &operator=(const EnumeratedRange &v) {
|
||||
EnumeratedRange(EnumeratedRange &&it)
|
||||
noexcept(IsNothrowMoveConstructible<T>::value):
|
||||
p_range(move(it.p_range)), p_index(it.p_index) {}
|
||||
|
||||
EnumeratedRange &operator=(const EnumeratedRange &v)
|
||||
noexcept(IsNothrowCopyAssignable<T>::value) {
|
||||
p_range = v.p_range;
|
||||
p_index = v.p_index;
|
||||
return *this;
|
||||
}
|
||||
EnumeratedRange &operator=(EnumeratedRange &&v) {
|
||||
EnumeratedRange &operator=(EnumeratedRange &&v)
|
||||
noexcept(IsNothrowMoveAssignable<T>::value) {
|
||||
p_range = move(v.p_range);
|
||||
p_index = v.p_index;
|
||||
return *this;
|
||||
}
|
||||
EnumeratedRange &operator=(const T &v) {
|
||||
EnumeratedRange &operator=(const T &v)
|
||||
noexcept(IsNothrowCopyAssignable<T>::value) {
|
||||
p_range = v;
|
||||
p_index = 0;
|
||||
return *this;
|
||||
}
|
||||
EnumeratedRange &operator=(T &&v) {
|
||||
p_range = forward<T>(v);
|
||||
EnumeratedRange &operator=(T &&v)
|
||||
noexcept(IsNothrowMoveAssignable<T>::value) {
|
||||
p_range = move(v);
|
||||
p_index = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const { return p_range.empty(); }
|
||||
bool empty() const noexcept(noexcept(p_range.empty())) {
|
||||
return p_range.empty();
|
||||
}
|
||||
|
||||
void pop_first() { ++p_index; p_range.pop_first(); }
|
||||
void pop_first() noexcept(noexcept(p_range.pop_last())) {
|
||||
++p_index; p_range.pop_first();
|
||||
}
|
||||
|
||||
EnumeratedValue<r_ref, r_size> first() {
|
||||
EnumeratedValue<r_ref, r_size> first()
|
||||
noexcept(noexcept(p_range.first())) {
|
||||
return EnumeratedValue<r_ref, r_size> { p_index, p_range.first() };
|
||||
}
|
||||
EnumeratedValue<r_ref, r_size> first() const {
|
||||
EnumeratedValue<r_ref, r_size> first() const
|
||||
noexcept(noexcept(p_range.first())) {
|
||||
return EnumeratedValue<r_ref, r_size> { p_index, p_range.first() };
|
||||
}
|
||||
|
||||
bool operator==(const EnumeratedRange &v) const {
|
||||
bool operator==(const EnumeratedRange &v) const
|
||||
noexcept(noexcept(p_range == v.p_range)) {
|
||||
return p_range == v.p_range;
|
||||
}
|
||||
bool operator!=(const EnumeratedRange &v) const {
|
||||
bool operator!=(const EnumeratedRange &v) const
|
||||
noexcept(noexcept(p_range != v.p_range)) {
|
||||
return p_range != v.p_range;
|
||||
}
|
||||
|
||||
private:
|
||||
T p_range;
|
||||
r_size p_index;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
EnumeratedRange<T> enumerate(const T &it) {
|
||||
EnumeratedRange<T> enumerate(const T &it)
|
||||
noexcept(noexcept(EnumeratedRange<T>(it))) {
|
||||
return EnumeratedRange<T>(it);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -656,8 +656,11 @@ namespace octa {
|
|||
template<typename, bool> struct __OctaIsNothrowDtible;
|
||||
|
||||
template<typename T>
|
||||
struct __OctaIsNothrowDtible<T, false>: IntegralConstant<bool,
|
||||
noexcept(__octa_declval<T>().~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>
|
||||
|
|
|
@ -31,12 +31,15 @@ namespace octa {
|
|||
|
||||
template<typename T> AddRvalueReference<T> declval();
|
||||
|
||||
template<typename T> void swap(T &a, T &b) {
|
||||
template<typename T> void swap(T &a, T &b)
|
||||
noexcept(IsNothrowMoveConstructible<T>::value
|
||||
&& IsNothrowMoveAssignable<T>::value) {
|
||||
T c(move(a));
|
||||
a = move(b);
|
||||
b = move(c);
|
||||
}
|
||||
template<typename T, size_t N> void swap(T (&a)[N], T (&b)[N]) {
|
||||
template<typename T, size_t N> void swap(T (&a)[N], T (&b)[N])
|
||||
noexcept(noexcept(swap(*a, *b))) {
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
swap(a[i], b[i]);
|
||||
}
|
||||
|
|
116
octa/vector.h
116
octa/vector.h
|
@ -22,7 +22,10 @@ namespace octa {
|
|||
T *p_buf;
|
||||
size_t p_len, p_cap;
|
||||
|
||||
void insert_base(size_t idx, size_t n) {
|
||||
void insert_base(size_t idx, size_t n)
|
||||
noexcept(IsNothrowDestructible<T>::value
|
||||
&& IsNothrowMoveConstructible<T>::value
|
||||
&& IsNothrowMoveAssignable<T>::value) {
|
||||
if (p_len + n > p_cap) reserve(p_len + n);
|
||||
p_len += n;
|
||||
for (size_t i = p_len - 1; i > idx + n - 1; --i) {
|
||||
|
@ -43,25 +46,30 @@ namespace octa {
|
|||
typedef PointerRange< T> range;
|
||||
typedef PointerRange<const T> const_range;
|
||||
|
||||
Vector(): p_buf(nullptr), p_len(0), p_cap(0) {}
|
||||
Vector() noexcept: p_buf(nullptr), p_len(0), p_cap(0) {}
|
||||
|
||||
explicit Vector(size_t n, const T &val = T()): Vector() {
|
||||
explicit Vector(size_t n, const T &val = T())
|
||||
noexcept(IsNothrowCopyConstructible<T>::value): Vector() {
|
||||
p_buf = new uchar[n * sizeof(T)];
|
||||
p_len = p_cap = n;
|
||||
T *cur = p_buf, *last = p_buf + n;
|
||||
while (cur != last) new (cur++) T(val);
|
||||
}
|
||||
|
||||
Vector(const Vector &v): Vector() {
|
||||
Vector(const Vector &v)
|
||||
noexcept(IsNothrowDestructible<T>::value
|
||||
&& IsNothrowCopyConstructible<T>::value): Vector() {
|
||||
*this = v;
|
||||
}
|
||||
|
||||
Vector(Vector &&v): p_buf(v.p_buf), p_len(v.p_len), p_cap(v.p_cap) {
|
||||
Vector(Vector &&v) noexcept: p_buf(v.p_buf), p_len(v.p_len),
|
||||
p_cap(v.p_cap) {
|
||||
v.p_buf = nullptr;
|
||||
v.p_len = v.p_cap = 0;
|
||||
}
|
||||
|
||||
Vector(InitializerList<T> v): Vector() {
|
||||
Vector(InitializerList<T> v)
|
||||
noexcept(IsNothrowCopyConstructible<T>::value): Vector() {
|
||||
size_t len = v.length();
|
||||
const T *ptr = v.get();
|
||||
reserve(len);
|
||||
|
@ -70,11 +78,11 @@ namespace octa {
|
|||
p_len = len;
|
||||
}
|
||||
|
||||
~Vector() {
|
||||
~Vector() noexcept(IsNothrowDestructible<T>::value) {
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
void clear() noexcept(IsNothrowDestructible<T>::value) {
|
||||
if (p_cap > 0) {
|
||||
if (!octa::IsPod<T>()) {
|
||||
T *cur = p_buf, *last = p_buf + p_len;
|
||||
|
@ -86,7 +94,9 @@ namespace octa {
|
|||
}
|
||||
}
|
||||
|
||||
Vector<T> &operator=(const Vector<T> &v) {
|
||||
Vector<T> &operator=(const Vector<T> &v)
|
||||
noexcept(IsNothrowDestructible<T>::value
|
||||
&& IsNothrowCopyConstructible<T>::value) {
|
||||
if (this == &v) return *this;
|
||||
|
||||
if (p_cap >= v.p_cap) {
|
||||
|
@ -115,7 +125,8 @@ namespace octa {
|
|||
return *this;
|
||||
}
|
||||
|
||||
Vector<T> &operator=(Vector<T> &&v) {
|
||||
Vector<T> &operator=(Vector<T> &&v)
|
||||
noexcept(IsNothrowDestructible<T>::value) {
|
||||
clear();
|
||||
p_len = v.p_len;
|
||||
p_cap = v.p_cap;
|
||||
|
@ -123,7 +134,10 @@ namespace octa {
|
|||
return *this;
|
||||
}
|
||||
|
||||
void resize(size_t n, const T &v = T()) {
|
||||
void resize(size_t n, const T &v = T())
|
||||
noexcept(IsNothrowDestructible<T>::value
|
||||
&& IsNothrowMoveConstructible<T>::value
|
||||
&& IsNothrowCopyConstructible<T>::value) {
|
||||
size_t len = p_len;
|
||||
reserve(n);
|
||||
p_len = n;
|
||||
|
@ -138,7 +152,9 @@ namespace octa {
|
|||
}
|
||||
}
|
||||
|
||||
void reserve(size_t n) {
|
||||
void reserve(size_t n)
|
||||
noexcept(IsNothrowDestructible<T>::value
|
||||
&& IsNothrowMoveConstructible<T>::value) {
|
||||
if (n <= p_len) {
|
||||
if (n == p_len) return;
|
||||
while (p_len > n) pop();
|
||||
|
@ -167,19 +183,21 @@ namespace octa {
|
|||
p_buf = tmp;
|
||||
}
|
||||
|
||||
T &operator[](size_t i) { return p_buf[i]; }
|
||||
const T &operator[](size_t i) const { return p_buf[i]; }
|
||||
T &operator[](size_t i) noexcept { return p_buf[i]; }
|
||||
const T &operator[](size_t i) const noexcept { return p_buf[i]; }
|
||||
|
||||
T &at(size_t i) { return p_buf[i]; }
|
||||
const T &at(size_t i) const { return p_buf[i]; }
|
||||
T &at(size_t i) noexcept { return p_buf[i]; }
|
||||
const T &at(size_t i) const noexcept { return p_buf[i]; }
|
||||
|
||||
T &push(const T &v) {
|
||||
T &push(const T &v) noexcept(noexcept(reserve(p_len + 1))
|
||||
&& IsNothrowCopyConstructible<T>::value) {
|
||||
if (p_len == p_cap) reserve(p_len + 1);
|
||||
new (&p_buf[p_len]) T(v);
|
||||
return p_buf[p_len++];
|
||||
}
|
||||
|
||||
T &push() {
|
||||
T &push() noexcept(noexcept(reserve(p_len + 1))
|
||||
&& IsNothrowDefaultConstructible<T>::value) {
|
||||
if (p_len == p_cap) reserve(p_len + 1);
|
||||
new (&p_buf[p_len]) T;
|
||||
return p_buf[p_len++];
|
||||
|
@ -192,7 +210,7 @@ namespace octa {
|
|||
return p_buf[p_len++];
|
||||
}
|
||||
|
||||
void pop() {
|
||||
void pop() noexcept(IsNothrowDestructible<T>::value) {
|
||||
if (!octa::IsPod<T>()) {
|
||||
p_buf[--p_len].~T();
|
||||
} else {
|
||||
|
@ -200,50 +218,55 @@ namespace octa {
|
|||
}
|
||||
}
|
||||
|
||||
T &pop_ret() {
|
||||
T &pop_ret() noexcept {
|
||||
return p_buf[--p_len];
|
||||
}
|
||||
|
||||
T &first() { return p_buf[0]; }
|
||||
const T &first() const { return p_buf[0]; };
|
||||
T &first() noexcept { return p_buf[0]; }
|
||||
const T &first() const noexcept { return p_buf[0]; };
|
||||
|
||||
T &last() { return p_buf[p_len - 1]; }
|
||||
const T &last() const { return p_buf[p_len - 1]; }
|
||||
T &last() noexcept { return p_buf[p_len - 1]; }
|
||||
const T &last() const noexcept { return p_buf[p_len - 1]; }
|
||||
|
||||
T *get() { return p_buf; }
|
||||
const T *get() const { return p_buf; }
|
||||
T *get() noexcept { return p_buf; }
|
||||
const T *get() const noexcept { return p_buf; }
|
||||
|
||||
size_t length() const { return p_len; }
|
||||
size_t capacity() const { return p_cap; }
|
||||
size_t length() const noexcept { return p_len; }
|
||||
size_t capacity() const noexcept { return p_cap; }
|
||||
|
||||
bool empty() const { return (p_len == 0); }
|
||||
bool empty() const noexcept { return (p_len == 0); }
|
||||
|
||||
bool in_range(size_t idx) { return idx < p_len; }
|
||||
bool in_range(int idx) { return idx >= 0 && idx < p_len; }
|
||||
bool in_range(const T *ptr) {
|
||||
bool in_range(size_t idx) noexcept { return idx < p_len; }
|
||||
bool in_range(int idx) noexcept { return idx >= 0 && idx < p_len; }
|
||||
bool in_range(const T *ptr) noexcept {
|
||||
return ptr >= p_buf && ptr < &p_buf[p_len];
|
||||
}
|
||||
|
||||
T *disown() {
|
||||
T *disown() noexcept {
|
||||
T *r = p_buf;
|
||||
p_buf = nullptr;
|
||||
p_len = p_cap = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
T *insert(size_t idx, T &&v) {
|
||||
T *insert(size_t idx, T &&v)
|
||||
noexcept(noexcept(insert_base(idx, 1))) {
|
||||
insert_base(idx, 1);
|
||||
p_buf[idx] = forward<T>(v);
|
||||
p_buf[idx] = move(v);
|
||||
return &p_buf[idx];
|
||||
}
|
||||
|
||||
T *insert(size_t idx, const T &v) {
|
||||
T *insert(size_t idx, const T &v)
|
||||
noexcept(noexcept(insert_base(idx, 1))
|
||||
&& IsNothrowCopyAssignable<T>::value) {
|
||||
insert_base(idx, 1);
|
||||
p_buf[idx] = v;
|
||||
return &p_buf[idx];
|
||||
}
|
||||
|
||||
T *insert(size_t idx, size_t n, const T &v) {
|
||||
T *insert(size_t idx, size_t n, const T &v)
|
||||
noexcept(noexcept(insert_base(idx, 1))
|
||||
&& IsNothrowCopyAssignable<T>::value) {
|
||||
insert_base(idx, n);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
p_buf[idx + i] = v;
|
||||
|
@ -252,7 +275,13 @@ namespace octa {
|
|||
}
|
||||
|
||||
template<typename U>
|
||||
T *insert_range(size_t idx, U range) {
|
||||
T *insert_range(size_t idx, U range)
|
||||
noexcept(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();
|
||||
insert_base(idx, len);
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
|
@ -262,18 +291,19 @@ namespace octa {
|
|||
return &p_buf[idx];
|
||||
}
|
||||
|
||||
T *insert(size_t idx, InitializerList<T> il) {
|
||||
T *insert(size_t idx, InitializerList<T> il)
|
||||
noexcept(noexcept(insert_range(idx, il.range()))) {
|
||||
return insert_range(idx, il.range());
|
||||
}
|
||||
|
||||
range each() {
|
||||
range each() noexcept {
|
||||
return PointerRange<T>(p_buf, p_buf + p_len);
|
||||
}
|
||||
const_range each() const {
|
||||
const_range each() const noexcept {
|
||||
return PointerRange<const T>(p_buf, p_buf + p_len);
|
||||
}
|
||||
|
||||
void swap(Vector &v) {
|
||||
void swap(Vector &v) noexcept {
|
||||
swap(p_len, v.p_len);
|
||||
swap(p_cap, v.p_cap);
|
||||
swap(p_buf, v.p_buf);
|
||||
|
@ -281,7 +311,7 @@ namespace octa {
|
|||
};
|
||||
|
||||
template<typename T>
|
||||
void swap(Vector<T> &a, Vector<T> &b) {
|
||||
void swap(Vector<T> &a, Vector<T> &b) noexcept {
|
||||
a.swap(b);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue