deuglify template args
parent
47016ec6ad
commit
84d78ba87a
328
octa/algorithm.h
328
octa/algorithm.h
|
@ -17,9 +17,9 @@ namespace octa {
|
|||
|
||||
/* partitioning */
|
||||
|
||||
template<typename _R, typename _U>
|
||||
_R partition(_R range, _U pred) {
|
||||
_R ret = range;
|
||||
template<typename R, typename U>
|
||||
R partition(R range, U pred) {
|
||||
R ret = range;
|
||||
for (; !range.empty(); range.pop_front()) {
|
||||
if (pred(range.front())) {
|
||||
octa::swap(range.front(), ret.front());
|
||||
|
@ -29,8 +29,8 @@ _R partition(_R range, _U pred) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
template<typename _R, typename _P>
|
||||
bool is_partitioned(_R range, _P pred) {
|
||||
template<typename R, typename P>
|
||||
bool is_partitioned(R range, P pred) {
|
||||
for (; !range.empty() && pred(range.front()); range.pop_front());
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (pred(range.front())) return false;
|
||||
|
@ -40,12 +40,12 @@ bool is_partitioned(_R range, _P pred) {
|
|||
/* sorting */
|
||||
|
||||
namespace detail {
|
||||
template<typename _R, typename _C>
|
||||
void insort(_R range, _C compare) {
|
||||
octa::RangeSize<_R> rlen = range.size();
|
||||
for (octa::RangeSize<_R> i = 1; i < rlen; ++i) {
|
||||
octa::RangeSize<_R> j = i;
|
||||
octa::RangeReference<_R> v = range[i];
|
||||
template<typename R, typename C>
|
||||
void insort(R range, C compare) {
|
||||
octa::RangeSize<R> rlen = range.size();
|
||||
for (octa::RangeSize<R> i = 1; i < rlen; ++i) {
|
||||
octa::RangeSize<R> j = i;
|
||||
octa::RangeReference<R> v = range[i];
|
||||
while (j > 0 && !compare(range[j - 1], v)) {
|
||||
range[j] = range[j - 1];
|
||||
--j;
|
||||
|
@ -54,20 +54,20 @@ namespace detail {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename _T, typename _U>
|
||||
template<typename T, typename U>
|
||||
struct UnaryCompare {
|
||||
const _T &val;
|
||||
_U comp;
|
||||
bool operator()(const _T &v) const { return comp(v, val); }
|
||||
const T &val;
|
||||
U comp;
|
||||
bool operator()(const T &v) const { return comp(v, val); }
|
||||
};
|
||||
|
||||
template<typename _R, typename _C>
|
||||
void hs_sift_down(_R range, octa::RangeSize<_R> s,
|
||||
octa::RangeSize<_R> e, _C compare) {
|
||||
octa::RangeSize<_R> r = s;
|
||||
template<typename R, typename C>
|
||||
void hs_sift_down(R range, octa::RangeSize<R> s,
|
||||
octa::RangeSize<R> e, C compare) {
|
||||
octa::RangeSize<R> r = s;
|
||||
while ((r * 2 + 1) <= e) {
|
||||
octa::RangeSize<_R> ch = r * 2 + 1;
|
||||
octa::RangeSize<_R> sw = r;
|
||||
octa::RangeSize<R> ch = r * 2 + 1;
|
||||
octa::RangeSize<R> sw = r;
|
||||
if (compare(range[sw], range[ch]))
|
||||
sw = ch;
|
||||
if (((ch + 1) <= e) && compare(range[sw], range[ch + 1]))
|
||||
|
@ -79,15 +79,15 @@ namespace detail {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename _R, typename _C>
|
||||
void heapsort(_R range, _C compare) {
|
||||
octa::RangeSize<_R> len = range.size();
|
||||
octa::RangeSize<_R> st = (len - 2) / 2;
|
||||
template<typename R, typename C>
|
||||
void heapsort(R range, C compare) {
|
||||
octa::RangeSize<R> len = range.size();
|
||||
octa::RangeSize<R> st = (len - 2) / 2;
|
||||
for (;;) {
|
||||
octa::detail::hs_sift_down(range, st, len - 1, compare);
|
||||
if (st-- == 0) break;
|
||||
}
|
||||
octa::RangeSize<_R> e = len - 1;
|
||||
octa::RangeSize<R> e = len - 1;
|
||||
while (e > 0) {
|
||||
octa::swap(range[e], range[0]);
|
||||
--e;
|
||||
|
@ -95,8 +95,8 @@ namespace detail {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename _R, typename _C>
|
||||
void introloop(_R range, _C compare, RangeSize<_R> depth) {
|
||||
template<typename R, typename C>
|
||||
void introloop(R range, C compare, RangeSize<R> depth) {
|
||||
if (range.size() <= 10) {
|
||||
octa::detail::insort(range, compare);
|
||||
return;
|
||||
|
@ -105,201 +105,201 @@ namespace detail {
|
|||
octa::detail::heapsort(range, compare);
|
||||
return;
|
||||
}
|
||||
octa::RangeReference<_R> p = range[range.size() / 2];
|
||||
octa::RangeReference<R> p = range[range.size() / 2];
|
||||
octa::swap(p, range.back());
|
||||
_R r = octa::partition(range,
|
||||
octa::detail::UnaryCompare<decltype(p), _C>{ p, compare });
|
||||
_R l = range.slice(0, range.size() - r.size());
|
||||
R r = octa::partition(range,
|
||||
octa::detail::UnaryCompare<decltype(p), C>{ p, compare });
|
||||
R l = range.slice(0, range.size() - r.size());
|
||||
octa::swap(r.front(), r.back());
|
||||
octa::detail::introloop(l, compare, depth - 1);
|
||||
octa::detail::introloop(r, compare, depth - 1);
|
||||
}
|
||||
|
||||
template<typename _R, typename _C>
|
||||
void introsort(_R range, _C compare) {
|
||||
octa::detail::introloop(range, compare, octa::RangeSize<_R>(2
|
||||
template<typename R, typename C>
|
||||
void introsort(R range, C compare) {
|
||||
octa::detail::introloop(range, compare, octa::RangeSize<R>(2
|
||||
* (log(range.size()) / log(2))));
|
||||
}
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename _R, typename _C>
|
||||
void sort(_R range, _C compare) {
|
||||
template<typename R, typename C>
|
||||
void sort(R range, C compare) {
|
||||
octa::detail::introsort(range, compare);
|
||||
}
|
||||
|
||||
template<typename _R>
|
||||
void sort(_R range) {
|
||||
sort(range, octa::Less<RangeValue<_R>>());
|
||||
template<typename R>
|
||||
void sort(R range) {
|
||||
sort(range, octa::Less<RangeValue<R>>());
|
||||
}
|
||||
|
||||
/* min/max(_element) */
|
||||
|
||||
template<typename _T>
|
||||
inline const _T &min(const _T &a, const _T &b) {
|
||||
template<typename T>
|
||||
inline const T &min(const T &a, const T &b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
template<typename _T, typename _C>
|
||||
inline const _T &min(const _T &a, const _T &b, _C compare) {
|
||||
template<typename T, typename C>
|
||||
inline const T &min(const T &a, const T &b, C compare) {
|
||||
return compare(a, b) ? a : b;
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
inline const _T &max(const _T &a, const _T &b) {
|
||||
template<typename T>
|
||||
inline const T &max(const T &a, const T &b) {
|
||||
return (a < b) ? b : a;
|
||||
}
|
||||
template<typename _T, typename _C>
|
||||
inline const _T &max(const _T &a, const _T &b, _C compare) {
|
||||
template<typename T, typename C>
|
||||
inline const T &max(const T &a, const T &b, C compare) {
|
||||
return compare(a, b) ? b : a;
|
||||
}
|
||||
|
||||
template<typename _R>
|
||||
inline _R min_element(_R range) {
|
||||
_R r = range;
|
||||
template<typename R>
|
||||
inline R min_element(R range) {
|
||||
R r = range;
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (octa::min(r.front(), range.front()) == range.front())
|
||||
r = range;
|
||||
return r;
|
||||
}
|
||||
template<typename _R, typename _C>
|
||||
inline _R min_element(_R range, _C compare) {
|
||||
_R r = range;
|
||||
template<typename R, typename C>
|
||||
inline R min_element(R range, C compare) {
|
||||
R r = range;
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (octa::min(r.front(), range.front(), compare) == range.front())
|
||||
r = range;
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename _R>
|
||||
inline _R max_element(_R range) {
|
||||
_R r = range;
|
||||
template<typename R>
|
||||
inline R max_element(R range) {
|
||||
R r = range;
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (octa::max(r.front(), range.front()) == range.front())
|
||||
r = range;
|
||||
return r;
|
||||
}
|
||||
template<typename _R, typename _C>
|
||||
inline _R max_element(_R range, _C compare) {
|
||||
_R r = range;
|
||||
template<typename R, typename C>
|
||||
inline R max_element(R range, C compare) {
|
||||
R r = range;
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (octa::max(r.front(), range.front(), compare) == range.front())
|
||||
r = range;
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
inline _T min(std::initializer_list<_T> il) {
|
||||
template<typename T>
|
||||
inline T min(std::initializer_list<T> il) {
|
||||
return octa::min_element(octa::each(il)).front();
|
||||
}
|
||||
template<typename _T, typename _C>
|
||||
inline _T min(std::initializer_list<_T> il, _C compare) {
|
||||
template<typename T, typename C>
|
||||
inline T min(std::initializer_list<T> il, C compare) {
|
||||
return octa::min_element(octa::each(il), compare).front();
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
inline _T max(std::initializer_list<_T> il) {
|
||||
template<typename T>
|
||||
inline T max(std::initializer_list<T> il) {
|
||||
return octa::max_element(octa::each(il)).front();
|
||||
}
|
||||
|
||||
template<typename _T, typename _C>
|
||||
inline _T max(std::initializer_list<_T> il, _C compare) {
|
||||
template<typename T, typename C>
|
||||
inline T max(std::initializer_list<T> il, C compare) {
|
||||
return octa::max_element(octa::each(il), compare).front();
|
||||
}
|
||||
|
||||
/* clamp */
|
||||
|
||||
template<typename _T, typename _U>
|
||||
inline _T clamp(const _T &v, const _U &lo, const _U &hi) {
|
||||
return octa::max(_T(lo), octa::min(v, _T(hi)));
|
||||
template<typename T, typename U>
|
||||
inline T clamp(const T &v, const U &lo, const U &hi) {
|
||||
return octa::max(T(lo), octa::min(v, T(hi)));
|
||||
}
|
||||
|
||||
template<typename _T, typename _U, typename _C>
|
||||
inline _T clamp(const _T &v, const _U &lo, const _U &hi, _C compare) {
|
||||
return octa::max(_T(lo), octa::min(v, _T(hi), compare), compare);
|
||||
template<typename T, typename U, typename C>
|
||||
inline T clamp(const T &v, const U &lo, const U &hi, C compare) {
|
||||
return octa::max(T(lo), octa::min(v, T(hi), compare), compare);
|
||||
}
|
||||
|
||||
/* algos that don't change the range */
|
||||
|
||||
template<typename _R, typename _F>
|
||||
_F for_each(_R range, _F func) {
|
||||
template<typename R, typename F>
|
||||
F for_each(R range, F func) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
func(range.front());
|
||||
return octa::move(func);
|
||||
}
|
||||
|
||||
template<typename _R, typename _P>
|
||||
bool all_of(_R range, _P pred) {
|
||||
template<typename R, typename P>
|
||||
bool all_of(R range, P pred) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (!pred(range.front())) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename _R, typename _P>
|
||||
bool any_of(_R range, _P pred) {
|
||||
template<typename R, typename P>
|
||||
bool any_of(R range, P pred) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (pred(range.front())) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename _R, typename _P>
|
||||
bool none_of(_R range, _P pred) {
|
||||
template<typename R, typename P>
|
||||
bool none_of(R range, P pred) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (pred(range.front())) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename _R, typename _T>
|
||||
_R find(_R range, const _T &v) {
|
||||
template<typename R, typename T>
|
||||
R find(R range, const T &v) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (range.front() == v)
|
||||
break;
|
||||
return range;
|
||||
}
|
||||
|
||||
template<typename _R, typename _P>
|
||||
_R find_if(_R range, _P pred) {
|
||||
template<typename R, typename P>
|
||||
R find_if(R range, P pred) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (pred(range.front()))
|
||||
break;
|
||||
return range;
|
||||
}
|
||||
|
||||
template<typename _R, typename _P>
|
||||
_R find_if_not(_R range, _P pred) {
|
||||
template<typename R, typename P>
|
||||
R find_if_not(R range, P pred) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (!pred(range.front()))
|
||||
break;
|
||||
return range;
|
||||
}
|
||||
|
||||
template<typename _R, typename _T>
|
||||
RangeSize<_R> count(_R range, const _T &v) {
|
||||
RangeSize<_R> ret = 0;
|
||||
template<typename R, typename T>
|
||||
RangeSize<R> count(R range, const T &v) {
|
||||
RangeSize<R> ret = 0;
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (range.front() == v)
|
||||
++ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename _R, typename _P>
|
||||
RangeSize<_R> count_if(_R range, _P pred) {
|
||||
RangeSize<_R> ret = 0;
|
||||
template<typename R, typename P>
|
||||
RangeSize<R> count_if(R range, P pred) {
|
||||
RangeSize<R> ret = 0;
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (pred(range.front()))
|
||||
++ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename _R, typename _P>
|
||||
RangeSize<_R> count_if_not(_R range, _P pred) {
|
||||
RangeSize<_R> ret = 0;
|
||||
template<typename R, typename P>
|
||||
RangeSize<R> count_if_not(R range, P pred) {
|
||||
RangeSize<R> ret = 0;
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (!pred(range.front()))
|
||||
++ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename _R>
|
||||
bool equal(_R range1, _R range2) {
|
||||
template<typename R>
|
||||
bool equal(R range1, R range2) {
|
||||
for (; !range1.empty(); range1.pop_front()) {
|
||||
if (range2.empty() || (range1.front() != range2.front()))
|
||||
return false;
|
||||
|
@ -310,38 +310,38 @@ bool equal(_R range1, _R range2) {
|
|||
|
||||
/* algos that modify ranges or work with output ranges */
|
||||
|
||||
template<typename _R1, typename _R2>
|
||||
_R2 copy(_R1 irange, _R2 orange) {
|
||||
template<typename R1, typename R2>
|
||||
R2 copy(R1 irange, R2 orange) {
|
||||
for (; !irange.empty(); irange.pop_front())
|
||||
orange.put(irange.front());
|
||||
return orange;
|
||||
}
|
||||
|
||||
template<typename _R1, typename _R2, typename _P>
|
||||
_R2 copy_if(_R1 irange, _R2 orange, _P pred) {
|
||||
template<typename R1, typename R2, typename P>
|
||||
R2 copy_if(R1 irange, R2 orange, P pred) {
|
||||
for (; !irange.empty(); irange.pop_front())
|
||||
if (pred(irange.front()))
|
||||
orange.put(irange.front());
|
||||
return orange;
|
||||
}
|
||||
|
||||
template<typename _R1, typename _R2, typename _P>
|
||||
_R2 copy_if_not(_R1 irange, _R2 orange, _P pred) {
|
||||
template<typename R1, typename R2, typename P>
|
||||
R2 copy_if_not(R1 irange, R2 orange, P pred) {
|
||||
for (; !irange.empty(); irange.pop_front())
|
||||
if (!pred(irange.front()))
|
||||
orange.put(irange.front());
|
||||
return orange;
|
||||
}
|
||||
|
||||
template<typename _R1, typename _R2>
|
||||
_R2 move(_R1 irange, _R2 orange) {
|
||||
template<typename R1, typename R2>
|
||||
R2 move(R1 irange, R2 orange) {
|
||||
for (; !irange.empty(); irange.pop_front())
|
||||
orange.put(octa::move(irange.front()));
|
||||
return orange;
|
||||
}
|
||||
|
||||
template<typename _R>
|
||||
void reverse(_R range) {
|
||||
template<typename R>
|
||||
void reverse(R range) {
|
||||
while (!range.empty()) {
|
||||
octa::swap(range.front(), range.back());
|
||||
range.pop_front();
|
||||
|
@ -349,27 +349,27 @@ void reverse(_R range) {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename _R1, typename _R2>
|
||||
_R2 reverse_copy(_R1 irange, _R2 orange) {
|
||||
template<typename R1, typename R2>
|
||||
R2 reverse_copy(R1 irange, R2 orange) {
|
||||
for (; !irange.empty(); irange.pop_back())
|
||||
orange.put(irange.back());
|
||||
return orange;
|
||||
}
|
||||
|
||||
template<typename _R, typename _T>
|
||||
void fill(_R range, const _T &v) {
|
||||
template<typename R, typename T>
|
||||
void fill(R range, const T &v) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
range.front() = v;
|
||||
}
|
||||
|
||||
template<typename _R, typename _F>
|
||||
void generate(_R range, _F gen) {
|
||||
template<typename R, typename F>
|
||||
void generate(R range, F gen) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
range.front() = gen();
|
||||
}
|
||||
|
||||
template<typename _R1, typename _R2>
|
||||
octa::Pair<_R1, _R2> swap_ranges(_R1 range1, _R2 range2) {
|
||||
template<typename R1, typename R2>
|
||||
octa::Pair<R1, R2> swap_ranges(R1 range1, R2 range2) {
|
||||
while (!range1.empty() && !range2.empty()) {
|
||||
octa::swap(range1.front(), range2.front());
|
||||
range1.pop_front();
|
||||
|
@ -378,52 +378,52 @@ octa::Pair<_R1, _R2> swap_ranges(_R1 range1, _R2 range2) {
|
|||
return octa::make_pair(range1, range2);
|
||||
}
|
||||
|
||||
template<typename _R, typename _T>
|
||||
void iota(_R range, _T value) {
|
||||
template<typename R, typename T>
|
||||
void iota(R range, T value) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
range.front() = value++;
|
||||
}
|
||||
|
||||
template<typename _R, typename _T>
|
||||
_T foldl(_R range, _T init) {
|
||||
template<typename R, typename T>
|
||||
T foldl(R range, T init) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
init = init + range.front();
|
||||
return init;
|
||||
}
|
||||
|
||||
template<typename _R, typename _T, typename _F>
|
||||
_T foldl(_R range, _T init, _F func) {
|
||||
template<typename R, typename T, typename F>
|
||||
T foldl(R range, T init, F func) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
init = func(init, range.front());
|
||||
return init;
|
||||
}
|
||||
|
||||
template<typename _R, typename _T>
|
||||
_T foldr(_R range, _T init) {
|
||||
template<typename R, typename T>
|
||||
T foldr(R range, T init) {
|
||||
for (; !range.empty(); range.pop_back())
|
||||
init = init + range.back();
|
||||
return init;
|
||||
}
|
||||
|
||||
template<typename _R, typename _T, typename _F>
|
||||
_T foldr(_R range, _T init, _F func) {
|
||||
template<typename R, typename T, typename F>
|
||||
T foldr(R range, T init, F func) {
|
||||
for (; !range.empty(); range.pop_back())
|
||||
init = func(init, range.back());
|
||||
return init;
|
||||
}
|
||||
|
||||
template<typename _T, typename _R>
|
||||
template<typename T, typename R>
|
||||
struct MapRange: InputRange<
|
||||
MapRange<_T, _R>, octa::RangeCategory<_T>, _R, _R, octa::RangeSize<_T>
|
||||
MapRange<T, R>, octa::RangeCategory<T>, R, R, octa::RangeSize<T>
|
||||
> {
|
||||
private:
|
||||
_T p_range;
|
||||
octa::Function<_R(octa::RangeReference<_T>)> p_func;
|
||||
T p_range;
|
||||
octa::Function<R(octa::RangeReference<T>)> p_func;
|
||||
|
||||
public:
|
||||
MapRange(): p_range(), p_func() {}
|
||||
template<typename _F>
|
||||
MapRange(const _T &range, const _F &func):
|
||||
template<typename F>
|
||||
MapRange(const T &range, const F &func):
|
||||
p_range(range), p_func(func) {}
|
||||
MapRange(const MapRange &it):
|
||||
p_range(it.p_range), p_func(it.p_func) {}
|
||||
|
@ -442,7 +442,7 @@ public:
|
|||
}
|
||||
|
||||
bool empty() const { return p_range.empty(); }
|
||||
octa::RangeSize<_T> size() const { return p_range.size(); }
|
||||
octa::RangeSize<T> size() const { return p_range.size(); }
|
||||
|
||||
bool equals_front(const MapRange &r) const {
|
||||
return p_range.equals_front(r.p_range);
|
||||
|
@ -451,10 +451,10 @@ public:
|
|||
return p_range.equals_front(r.p_range);
|
||||
}
|
||||
|
||||
octa::RangeDifference<_T> distance_front(const MapRange &r) const {
|
||||
octa::RangeDifference<T> distance_front(const MapRange &r) const {
|
||||
return p_range.distance_front(r.p_range);
|
||||
}
|
||||
octa::RangeDifference<_T> distance_back(const MapRange &r) const {
|
||||
octa::RangeDifference<T> distance_back(const MapRange &r) const {
|
||||
return p_range.distance_back(r.p_range);
|
||||
}
|
||||
|
||||
|
@ -464,54 +464,54 @@ public:
|
|||
bool push_front() { return p_range.pop_front(); }
|
||||
bool push_back() { return p_range.push_back(); }
|
||||
|
||||
octa::RangeSize<_T> pop_front_n(octa::RangeSize<_T> n) {
|
||||
octa::RangeSize<T> pop_front_n(octa::RangeSize<T> n) {
|
||||
p_range.pop_front_n(n);
|
||||
}
|
||||
octa::RangeSize<_T> pop_back_n(octa::RangeSize<_T> n) {
|
||||
octa::RangeSize<T> pop_back_n(octa::RangeSize<T> n) {
|
||||
p_range.pop_back_n(n);
|
||||
}
|
||||
|
||||
octa::RangeSize<_T> push_front_n(octa::RangeSize<_T> n) {
|
||||
octa::RangeSize<T> push_front_n(octa::RangeSize<T> n) {
|
||||
return p_range.push_front_n(n);
|
||||
}
|
||||
octa::RangeSize<_T> push_back_n(octa::RangeSize<_T> n) {
|
||||
octa::RangeSize<T> push_back_n(octa::RangeSize<T> n) {
|
||||
return p_range.push_back_n(n);
|
||||
}
|
||||
|
||||
_R front() const { return p_func(p_range.front()); }
|
||||
_R back() const { return p_func(p_range.back()); }
|
||||
R front() const { return p_func(p_range.front()); }
|
||||
R back() const { return p_func(p_range.back()); }
|
||||
|
||||
_R operator[](octa::RangeSize<_T> idx) const {
|
||||
R operator[](octa::RangeSize<T> idx) const {
|
||||
return p_func(p_range[idx]);
|
||||
}
|
||||
|
||||
MapRange<_T, _R> slice(octa::RangeSize<_T> start,
|
||||
octa::RangeSize<_T> end) {
|
||||
return MapRange<_T, _R>(p_range.slice(start, end), p_func);
|
||||
MapRange<T, R> slice(octa::RangeSize<T> start,
|
||||
octa::RangeSize<T> end) {
|
||||
return MapRange<T, R>(p_range.slice(start, end), p_func);
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename _R, typename _F> using MapReturnType
|
||||
= decltype(declval<_F>()(octa::declval<octa::RangeReference<_R>>()));
|
||||
template<typename R, typename F> using MapReturnType
|
||||
= decltype(declval<F>()(octa::declval<octa::RangeReference<R>>()));
|
||||
}
|
||||
|
||||
template<typename _R, typename _F>
|
||||
MapRange<_R, octa::detail::MapReturnType<_R, _F>> map(_R range,
|
||||
_F func) {
|
||||
return octa::MapRange<_R, octa::detail::MapReturnType<_R, _F>>(range,
|
||||
template<typename R, typename F>
|
||||
MapRange<R, octa::detail::MapReturnType<R, F>> map(R range,
|
||||
F func) {
|
||||
return octa::MapRange<R, octa::detail::MapReturnType<R, F>>(range,
|
||||
func);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
struct FilterRange: InputRange<
|
||||
FilterRange<_T>, octa::CommonType<octa::RangeCategory<_T>,
|
||||
FilterRange<T>, octa::CommonType<octa::RangeCategory<T>,
|
||||
octa::ForwardRangeTag>,
|
||||
octa::RangeValue<_T>, octa::RangeReference<_T>, octa::RangeSize<_T>
|
||||
octa::RangeValue<T>, octa::RangeReference<T>, octa::RangeSize<T>
|
||||
> {
|
||||
private:
|
||||
_T p_range;
|
||||
octa::Function<bool(octa::RangeReference<_T>)> p_pred;
|
||||
T p_range;
|
||||
octa::Function<bool(octa::RangeReference<T>)> p_pred;
|
||||
|
||||
void advance_valid() {
|
||||
while (!p_range.empty() && !p_pred(front())) p_range.pop_front();
|
||||
|
@ -520,8 +520,8 @@ private:
|
|||
public:
|
||||
FilterRange(): p_range(), p_pred() {}
|
||||
|
||||
template<typename _P>
|
||||
FilterRange(const _T &range, const _P &pred): p_range(range),
|
||||
template<typename P>
|
||||
FilterRange(const T &range, const P &pred): p_range(range),
|
||||
p_pred(pred) {
|
||||
advance_valid();
|
||||
}
|
||||
|
@ -559,7 +559,7 @@ public:
|
|||
return ret;
|
||||
}
|
||||
bool push_front() {
|
||||
_T tmp = p_range;
|
||||
T tmp = p_range;
|
||||
if (!tmp.push_front()) return false;
|
||||
while (!p_pred(tmp.front()))
|
||||
if (!tmp.push_front())
|
||||
|
@ -568,12 +568,12 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
octa::RangeReference<_T> front() const { return p_range.front(); }
|
||||
octa::RangeReference<T> front() const { return p_range.front(); }
|
||||
};
|
||||
|
||||
template<typename _R, typename _P>
|
||||
FilterRange<_R> filter(_R range, _P pred) {
|
||||
return octa::FilterRange<_R>(range, pred);
|
||||
template<typename R, typename P>
|
||||
FilterRange<R> filter(R range, P pred) {
|
||||
return octa::FilterRange<R>(range, pred);
|
||||
}
|
||||
|
||||
} /* namespace octa */
|
||||
|
|
54
octa/array.h
54
octa/array.h
|
@ -14,55 +14,55 @@
|
|||
|
||||
namespace octa {
|
||||
|
||||
template<typename _T, size_t _N>
|
||||
template<typename T, size_t N>
|
||||
struct Array {
|
||||
typedef size_t Size;
|
||||
typedef ptrdiff_t Difference;
|
||||
typedef _T Value;
|
||||
typedef _T &Reference;
|
||||
typedef const _T &ConstReference;
|
||||
typedef _T *Pointer;
|
||||
typedef const _T *ConstPointer;
|
||||
typedef PointerRange< _T> Range;
|
||||
typedef PointerRange<const _T> ConstRange;
|
||||
typedef T Value;
|
||||
typedef T &Reference;
|
||||
typedef const T &ConstReference;
|
||||
typedef T *Pointer;
|
||||
typedef const T *ConstPointer;
|
||||
typedef PointerRange< T> Range;
|
||||
typedef PointerRange<const T> ConstRange;
|
||||
|
||||
_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) { return p_buf[i]; }
|
||||
const T &operator[](size_t i) const { 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) { return p_buf[i]; }
|
||||
const T &at(size_t i) const { return p_buf[i]; }
|
||||
|
||||
_T &front() { return p_buf[0]; }
|
||||
const _T &front() const { return p_buf[0]; }
|
||||
T &front() { return p_buf[0]; }
|
||||
const T &front() const { return p_buf[0]; }
|
||||
|
||||
_T &back() { return p_buf[(_N > 0) ? (_N - 1) : 0]; }
|
||||
const _T &back() const { return p_buf[(_N > 0) ? (_N - 1) : 0]; }
|
||||
T &back() { return p_buf[(N > 0) ? (N - 1) : 0]; }
|
||||
const T &back() const { return p_buf[(N > 0) ? (N - 1) : 0]; }
|
||||
|
||||
size_t size() const { return _N; }
|
||||
size_t size() const { return N; }
|
||||
|
||||
bool empty() const { return _N == 0; }
|
||||
bool empty() const { return N == 0; }
|
||||
|
||||
bool in_range(size_t idx) { return idx < _N; }
|
||||
bool in_range(int idx) { return idx >= 0 && size_t(idx) < _N; }
|
||||
bool in_range(const _T *ptr) {
|
||||
return ptr >= &p_buf[0] && ptr < &p_buf[_N];
|
||||
bool in_range(size_t idx) { return idx < N; }
|
||||
bool in_range(int idx) { return idx >= 0 && size_t(idx) < N; }
|
||||
bool in_range(const T *ptr) {
|
||||
return ptr >= &p_buf[0] && ptr < &p_buf[N];
|
||||
}
|
||||
|
||||
_T *data() { return p_buf; }
|
||||
const _T *data() const { return p_buf; }
|
||||
T *data() { return p_buf; }
|
||||
const T *data() const { return p_buf; }
|
||||
|
||||
Range each() {
|
||||
return octa::PointerRange<_T>(p_buf, p_buf + _N);
|
||||
return octa::PointerRange<T>(p_buf, p_buf + N);
|
||||
}
|
||||
ConstRange each() const {
|
||||
return octa::PointerRange<const _T>(p_buf, p_buf + _N);
|
||||
return octa::PointerRange<const T>(p_buf, p_buf + N);
|
||||
}
|
||||
|
||||
void swap(Array &v) {
|
||||
octa::swap_ranges(each(), v.each());
|
||||
}
|
||||
|
||||
_T p_buf[(_N > 0) ? _N : 1];
|
||||
T p_buf[(N > 0) ? N : 1];
|
||||
};
|
||||
|
||||
} /* namespace octa */
|
||||
|
|
640
octa/atomic.h
640
octa/atomic.h
File diff suppressed because it is too large
Load Diff
|
@ -16,12 +16,12 @@ namespace octa {
|
|||
/* basic function objects */
|
||||
|
||||
#define OCTA_DEFINE_BINARY_OP(_name, _op, _rettype) \
|
||||
template<typename _T> struct _name { \
|
||||
_rettype operator()(const _T &x, const _T &y) const { \
|
||||
template<typename T> struct _name { \
|
||||
_rettype operator()(const T &x, const T &y) const { \
|
||||
return x _op y; \
|
||||
} \
|
||||
typedef _T FirstArgument; \
|
||||
typedef _T SecondArgument; \
|
||||
typedef T FirstArgument; \
|
||||
typedef T SecondArgument; \
|
||||
typedef _rettype Result; \
|
||||
};
|
||||
|
||||
|
@ -33,80 +33,80 @@ OCTA_DEFINE_BINARY_OP(Equal, ==, bool)
|
|||
OCTA_DEFINE_BINARY_OP(NotEqual, !=, bool)
|
||||
OCTA_DEFINE_BINARY_OP(LogicalAnd, &&, bool)
|
||||
OCTA_DEFINE_BINARY_OP(LogicalOr, ||, bool)
|
||||
OCTA_DEFINE_BINARY_OP(Modulus, %, _T)
|
||||
OCTA_DEFINE_BINARY_OP(Multiplies, *, _T)
|
||||
OCTA_DEFINE_BINARY_OP(Divides, /, _T)
|
||||
OCTA_DEFINE_BINARY_OP(Plus, +, _T)
|
||||
OCTA_DEFINE_BINARY_OP(Minus, -, _T)
|
||||
OCTA_DEFINE_BINARY_OP(BitAnd, &, _T)
|
||||
OCTA_DEFINE_BINARY_OP(BitOr, |, _T)
|
||||
OCTA_DEFINE_BINARY_OP(BitXor, ^, _T)
|
||||
OCTA_DEFINE_BINARY_OP(Modulus, %, T)
|
||||
OCTA_DEFINE_BINARY_OP(Multiplies, *, T)
|
||||
OCTA_DEFINE_BINARY_OP(Divides, /, T)
|
||||
OCTA_DEFINE_BINARY_OP(Plus, +, T)
|
||||
OCTA_DEFINE_BINARY_OP(Minus, -, T)
|
||||
OCTA_DEFINE_BINARY_OP(BitAnd, &, T)
|
||||
OCTA_DEFINE_BINARY_OP(BitOr, |, T)
|
||||
OCTA_DEFINE_BINARY_OP(BitXor, ^, T)
|
||||
|
||||
#undef OCTA_DEFINE_BINARY_OP
|
||||
|
||||
template<typename _T> struct LogicalNot {
|
||||
bool operator()(const _T &x) const { return !x; }
|
||||
typedef _T Argument;
|
||||
template<typename T> struct LogicalNot {
|
||||
bool operator()(const T &x) const { return !x; }
|
||||
typedef T Argument;
|
||||
typedef bool Result;
|
||||
};
|
||||
|
||||
template<typename _T> struct Negate {
|
||||
bool operator()(const _T &x) const { return -x; }
|
||||
typedef _T Argument;
|
||||
typedef _T Result;
|
||||
template<typename T> struct Negate {
|
||||
bool operator()(const T &x) const { return -x; }
|
||||
typedef T Argument;
|
||||
typedef T Result;
|
||||
};
|
||||
|
||||
template<typename _T> struct BinaryNegate {
|
||||
typedef typename _T::FirstArgument FirstArgument;
|
||||
typedef typename _T::SecondArgument SecondArgument;
|
||||
template<typename T> struct BinaryNegate {
|
||||
typedef typename T::FirstArgument FirstArgument;
|
||||
typedef typename T::SecondArgument SecondArgument;
|
||||
typedef bool Result;
|
||||
|
||||
explicit BinaryNegate(const _T &f): p_fn(f) {}
|
||||
explicit BinaryNegate(const T &f): p_fn(f) {}
|
||||
|
||||
bool operator()(const FirstArgument &x,
|
||||
const SecondArgument &y) {
|
||||
return !p_fn(x, y);
|
||||
}
|
||||
private:
|
||||
_T p_fn;
|
||||
T p_fn;
|
||||
};
|
||||
|
||||
template<typename _T> struct UnaryNegate {
|
||||
typedef typename _T::Argument Argument;
|
||||
template<typename T> struct UnaryNegate {
|
||||
typedef typename T::Argument Argument;
|
||||
typedef bool Result;
|
||||
|
||||
explicit UnaryNegate(const _T &f): p_fn(f) {}
|
||||
explicit UnaryNegate(const T &f): p_fn(f) {}
|
||||
bool operator()(const Argument &x) {
|
||||
return !p_fn(x);
|
||||
}
|
||||
private:
|
||||
_T p_fn;
|
||||
T p_fn;
|
||||
};
|
||||
|
||||
template<typename _T> UnaryNegate<_T> not1(const _T &fn) {
|
||||
return UnaryNegate<_T>(fn);
|
||||
template<typename T> UnaryNegate<T> not1(const T &fn) {
|
||||
return UnaryNegate<T>(fn);
|
||||
}
|
||||
|
||||
template<typename _T> BinaryNegate<_T> not2(const _T &fn) {
|
||||
return BinaryNegate<_T>(fn);
|
||||
template<typename T> BinaryNegate<T> not2(const T &fn) {
|
||||
return BinaryNegate<T>(fn);
|
||||
}
|
||||
|
||||
/* hash */
|
||||
|
||||
template<typename _T> struct Hash;
|
||||
template<typename T> struct Hash;
|
||||
|
||||
namespace detail {
|
||||
template<typename _T> struct HashBase {
|
||||
typedef _T Argument;
|
||||
template<typename T> struct HashBase {
|
||||
typedef T Argument;
|
||||
typedef size_t Result;
|
||||
|
||||
size_t operator()(_T v) const {
|
||||
size_t operator()(T v) const {
|
||||
return size_t(v);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#define OCTA_HASH_BASIC(_T) template<> struct Hash<_T>: octa::detail::HashBase<_T> {};
|
||||
#define OCTA_HASH_BASIC(T) template<> struct Hash<T>: octa::detail::HashBase<T> {};
|
||||
|
||||
OCTA_HASH_BASIC(bool)
|
||||
OCTA_HASH_BASIC(char)
|
||||
|
@ -132,60 +132,60 @@ namespace detail {
|
|||
return h;
|
||||
}
|
||||
|
||||
template<typename _T, size_t = sizeof(_T) / sizeof(size_t)>
|
||||
template<typename T, size_t = sizeof(T) / sizeof(size_t)>
|
||||
struct ScalarHash;
|
||||
|
||||
template<typename _T> struct ScalarHash<_T, 0> {
|
||||
typedef _T Argument;
|
||||
template<typename T> struct ScalarHash<T, 0> {
|
||||
typedef T Argument;
|
||||
typedef size_t Result;
|
||||
|
||||
size_t operator()(_T v) const {
|
||||
union { _T v; size_t h; } u;
|
||||
size_t operator()(T v) const {
|
||||
union { T v; size_t h; } u;
|
||||
u.h = 0;
|
||||
u.v = v;
|
||||
return u.h;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T> struct ScalarHash<_T, 1> {
|
||||
typedef _T Argument;
|
||||
template<typename T> struct ScalarHash<T, 1> {
|
||||
typedef T Argument;
|
||||
typedef size_t Result;
|
||||
|
||||
size_t operator()(_T v) const {
|
||||
union { _T v; size_t h; } u;
|
||||
size_t operator()(T v) const {
|
||||
union { T v; size_t h; } u;
|
||||
u.v = v;
|
||||
return u.h;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T> struct ScalarHash<_T, 2> {
|
||||
typedef _T Argument;
|
||||
template<typename T> struct ScalarHash<T, 2> {
|
||||
typedef T Argument;
|
||||
typedef size_t Result;
|
||||
|
||||
size_t operator()(_T v) const {
|
||||
union { _T v; struct { size_t h1, h2; }; } u;
|
||||
size_t operator()(T v) const {
|
||||
union { T v; struct { size_t h1, h2; }; } u;
|
||||
u.v = v;
|
||||
return mem_hash((const void *)&u, sizeof(u));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T> struct ScalarHash<_T, 3> {
|
||||
typedef _T Argument;
|
||||
template<typename T> struct ScalarHash<T, 3> {
|
||||
typedef T Argument;
|
||||
typedef size_t Result;
|
||||
|
||||
size_t operator()(_T v) const {
|
||||
union { _T v; struct { size_t h1, h2, h3; }; } u;
|
||||
size_t operator()(T v) const {
|
||||
union { T v; struct { size_t h1, h2, h3; }; } u;
|
||||
u.v = v;
|
||||
return mem_hash((const void *)&u, sizeof(u));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T> struct ScalarHash<_T, 4> {
|
||||
typedef _T Argument;
|
||||
template<typename T> struct ScalarHash<T, 4> {
|
||||
typedef T Argument;
|
||||
typedef size_t Result;
|
||||
|
||||
size_t operator()(_T v) const {
|
||||
union { _T v; struct { size_t h1, h2, h3, h4; }; } u;
|
||||
size_t operator()(T v) const {
|
||||
union { T v; struct { size_t h1, h2, h3, h4; }; } u;
|
||||
u.v = v;
|
||||
return mem_hash((const void *)&u, sizeof(u));
|
||||
}
|
||||
|
@ -230,12 +230,12 @@ template<> struct Hash<ldouble>: octa::detail::ScalarHash<ldouble> {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename _T> struct Hash<_T *> {
|
||||
typedef _T *Argument;
|
||||
template<typename T> struct Hash<T *> {
|
||||
typedef T *Argument;
|
||||
typedef size_t Result;
|
||||
|
||||
size_t operator()(_T *v) const {
|
||||
union { _T *v; size_t h; } u;
|
||||
size_t operator()(T *v) const {
|
||||
union { T *v; size_t h; } u;
|
||||
u.v = v;
|
||||
return octa::detail::mem_hash((const void *)&u, sizeof(u));
|
||||
}
|
||||
|
@ -243,101 +243,101 @@ template<typename _T> struct Hash<_T *> {
|
|||
|
||||
/* reference wrapper */
|
||||
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
struct ReferenceWrapper {
|
||||
typedef _T type;
|
||||
typedef T type;
|
||||
|
||||
ReferenceWrapper(_T &v): p_ptr(address_of(v)) {}
|
||||
ReferenceWrapper(T &v): p_ptr(address_of(v)) {}
|
||||
ReferenceWrapper(const ReferenceWrapper &) = default;
|
||||
ReferenceWrapper(_T &&) = delete;
|
||||
ReferenceWrapper(T &&) = delete;
|
||||
|
||||
ReferenceWrapper &operator=(const ReferenceWrapper &) = default;
|
||||
|
||||
operator _T &() const { return *p_ptr; }
|
||||
_T &get() const { return *p_ptr; }
|
||||
operator T &() const { return *p_ptr; }
|
||||
T &get() const { return *p_ptr; }
|
||||
|
||||
private:
|
||||
_T *p_ptr;
|
||||
T *p_ptr;
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
ReferenceWrapper<_T> ref(_T &v) {
|
||||
return ReferenceWrapper<_T>(v);
|
||||
template<typename T>
|
||||
ReferenceWrapper<T> ref(T &v) {
|
||||
return ReferenceWrapper<T>(v);
|
||||
}
|
||||
template<typename _T>
|
||||
ReferenceWrapper<_T> ref(ReferenceWrapper<_T> v) {
|
||||
return ReferenceWrapper<_T>(v);
|
||||
template<typename T>
|
||||
ReferenceWrapper<T> ref(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>
|
||||
ReferenceWrapper<const _T> cref(const _T &v) {
|
||||
return ReferenceWrapper<_T>(v);
|
||||
template<typename T>
|
||||
ReferenceWrapper<const T> cref(const T &v) {
|
||||
return ReferenceWrapper<T>(v);
|
||||
}
|
||||
template<typename _T>
|
||||
ReferenceWrapper<const _T> cref(ReferenceWrapper<_T> v) {
|
||||
return ReferenceWrapper<_T>(v);
|
||||
template<typename T>
|
||||
ReferenceWrapper<const T> cref(ReferenceWrapper<T> v) {
|
||||
return ReferenceWrapper<T>(v);
|
||||
}
|
||||
template<typename _T> void cref(const _T &&) = delete;
|
||||
template<typename T> void cref(const T &&) = delete;
|
||||
|
||||
/* mem_fn */
|
||||
|
||||
namespace detail {
|
||||
template<typename, typename> struct MemTypes;
|
||||
template<typename _T, typename _R, typename ..._A>
|
||||
struct MemTypes<_T, _R(_A...)> {
|
||||
typedef _R Result;
|
||||
typedef _T Argument;
|
||||
template<typename T, typename R, typename ...A>
|
||||
struct MemTypes<T, R(A...)> {
|
||||
typedef R Result;
|
||||
typedef T Argument;
|
||||
};
|
||||
template<typename _T, typename _R, typename _A>
|
||||
struct MemTypes<_T, _R(_A)> {
|
||||
typedef _R Result;
|
||||
typedef _T FirstArgument;
|
||||
typedef _A SecondArgument;
|
||||
template<typename T, typename R, typename A>
|
||||
struct MemTypes<T, R(A)> {
|
||||
typedef R Result;
|
||||
typedef T FirstArgument;
|
||||
typedef A SecondArgument;
|
||||
};
|
||||
template<typename _T, typename _R, typename ..._A>
|
||||
struct MemTypes<_T, _R(_A...) const> {
|
||||
typedef _R Result;
|
||||
typedef const _T Argument;
|
||||
template<typename T, typename R, typename ...A>
|
||||
struct MemTypes<T, R(A...) const> {
|
||||
typedef R Result;
|
||||
typedef const T Argument;
|
||||
};
|
||||
template<typename _T, typename _R, typename _A>
|
||||
struct MemTypes<_T, _R(_A) const> {
|
||||
typedef _R Result;
|
||||
typedef const _T FirstArgument;
|
||||
typedef _A SecondArgument;
|
||||
template<typename T, typename R, typename A>
|
||||
struct MemTypes<T, R(A) const> {
|
||||
typedef R Result;
|
||||
typedef const T FirstArgument;
|
||||
typedef A SecondArgument;
|
||||
};
|
||||
|
||||
template<typename _R, typename _T>
|
||||
class MemFn: MemTypes<_T, _R> {
|
||||
_R _T::*p_ptr;
|
||||
template<typename R, typename T>
|
||||
class MemFn: MemTypes<T, R> {
|
||||
R T::*p_ptr;
|
||||
public:
|
||||
MemFn(_R _T::*ptr): p_ptr(ptr) {}
|
||||
template<typename... _A>
|
||||
auto operator()(_T &obj, _A &&...args) ->
|
||||
decltype(((obj).*(p_ptr))(forward<_A>(args)...)) {
|
||||
return ((obj).*(p_ptr))(forward<_A>(args)...);
|
||||
MemFn(R T::*ptr): p_ptr(ptr) {}
|
||||
template<typename... A>
|
||||
auto operator()(T &obj, A &&...args) ->
|
||||
decltype(((obj).*(p_ptr))(forward<A>(args)...)) {
|
||||
return ((obj).*(p_ptr))(forward<A>(args)...);
|
||||
}
|
||||
template<typename... _A>
|
||||
auto operator()(const _T &obj, _A &&...args) ->
|
||||
decltype(((obj).*(p_ptr))(forward<_A>(args)...)) const {
|
||||
return ((obj).*(p_ptr))(forward<_A>(args)...);
|
||||
template<typename... A>
|
||||
auto operator()(const T &obj, A &&...args) ->
|
||||
decltype(((obj).*(p_ptr))(forward<A>(args)...)) const {
|
||||
return ((obj).*(p_ptr))(forward<A>(args)...);
|
||||
}
|
||||
template<typename... _A>
|
||||
auto operator()(_T *obj, _A &&...args) ->
|
||||
decltype(((obj)->*(p_ptr))(forward<_A>(args)...)) {
|
||||
return ((obj)->*(p_ptr))(forward<_A>(args)...);
|
||||
template<typename... A>
|
||||
auto operator()(T *obj, A &&...args) ->
|
||||
decltype(((obj)->*(p_ptr))(forward<A>(args)...)) {
|
||||
return ((obj)->*(p_ptr))(forward<A>(args)...);
|
||||
}
|
||||
template<typename... _A>
|
||||
auto operator()(const _T *obj, _A &&...args) ->
|
||||
decltype(((obj)->*(p_ptr))(forward<_A>(args)...)) const {
|
||||
return ((obj)->*(p_ptr))(forward<_A>(args)...);
|
||||
template<typename... A>
|
||||
auto operator()(const T *obj, A &&...args) ->
|
||||
decltype(((obj)->*(p_ptr))(forward<A>(args)...)) const {
|
||||
return ((obj)->*(p_ptr))(forward<A>(args)...);
|
||||
}
|
||||
};
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename _R, typename _T>
|
||||
octa::detail::MemFn<_R, _T> mem_fn(_R _T:: *ptr) {
|
||||
return octa::detail::MemFn<_R, _T>(ptr);
|
||||
template<typename R, typename T>
|
||||
octa::detail::MemFn<R, T> mem_fn(R T:: *ptr) {
|
||||
return octa::detail::MemFn<R, T>(ptr);
|
||||
}
|
||||
|
||||
/* function impl
|
||||
|
@ -351,72 +351,72 @@ namespace detail {
|
|||
void *p1, *p2;
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
struct FunctorInPlace {
|
||||
static constexpr bool value = sizeof(_T) <= sizeof(FunctorData)
|
||||
&& (alignof(FunctorData) % alignof(_T)) == 0
|
||||
&& octa::IsMoveConstructible<_T>::value;
|
||||
static constexpr bool value = sizeof(T) <= sizeof(FunctorData)
|
||||
&& (alignof(FunctorData) % alignof(T)) == 0
|
||||
&& octa::IsMoveConstructible<T>::value;
|
||||
};
|
||||
|
||||
template<typename _T, typename _E = void>
|
||||
template<typename T, typename E = void>
|
||||
struct FunctorDataManager {
|
||||
template<typename _R, typename ..._A>
|
||||
static _R call(const FunctorData &s, _A ...args) {
|
||||
return ((_T &)s)(octa::forward<_A>(args)...);
|
||||
template<typename R, typename ...A>
|
||||
static R call(const FunctorData &s, A ...args) {
|
||||
return ((T &)s)(octa::forward<A>(args)...);
|
||||
}
|
||||
|
||||
static void store_f(FunctorData &s, _T v) {
|
||||
new (&get_ref(s)) _T(octa::forward<_T>(v));
|
||||
static void store_f(FunctorData &s, T v) {
|
||||
new (&get_ref(s)) T(octa::forward<T>(v));
|
||||
}
|
||||
|
||||
static void move_f(FunctorData &lhs, FunctorData &&rhs) {
|
||||
new (&get_ref(lhs)) _T(octa::move(get_ref(rhs)));
|
||||
new (&get_ref(lhs)) T(octa::move(get_ref(rhs)));
|
||||
}
|
||||
|
||||
static void destroy_f(FunctorData &s) {
|
||||
get_ref(s).~_T();
|
||||
get_ref(s).~T();
|
||||
}
|
||||
|
||||
static _T &get_ref(const FunctorData &s) {
|
||||
return (_T &)s;
|
||||
static T &get_ref(const FunctorData &s) {
|
||||
return (T &)s;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
struct FunctorDataManager<_T,
|
||||
EnableIf<!FunctorInPlace<_T>::value>
|
||||
template<typename T>
|
||||
struct FunctorDataManager<T,
|
||||
EnableIf<!FunctorInPlace<T>::value>
|
||||
> {
|
||||
template<typename _R, typename ..._A>
|
||||
static _R call(const FunctorData &s, _A ...args) {
|
||||
return (*(_T *&)s)(octa::forward<_A>(args)...);
|
||||
template<typename R, typename ...A>
|
||||
static R call(const FunctorData &s, A ...args) {
|
||||
return (*(T *&)s)(octa::forward<A>(args)...);
|
||||
}
|
||||
|
||||
static void store_f(FunctorData &s, _T v) {
|
||||
new (&get_ptr_ref(s)) _T *(new _T(octa::forward<_T>(v)));
|
||||
static void store_f(FunctorData &s, T v) {
|
||||
new (&get_ptr_ref(s)) T *(new T(octa::forward<T>(v)));
|
||||
}
|
||||
|
||||
static void move_f(FunctorData &lhs, FunctorData &&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;
|
||||
}
|
||||
|
||||
static void destroy_f(FunctorData &s) {
|
||||
_T *&ptr = get_ptr_ref(s);
|
||||
T *&ptr = get_ptr_ref(s);
|
||||
if (!ptr) return;
|
||||
delete ptr;
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
static _T &get_ref(const FunctorData &s) {
|
||||
static T &get_ref(const FunctorData &s) {
|
||||
return *get_ptr_ref(s);
|
||||
}
|
||||
|
||||
static _T *&get_ptr_ref(FunctorData &s) {
|
||||
return (_T *&)s;
|
||||
static T *&get_ptr_ref(FunctorData &s) {
|
||||
return (T *&)s;
|
||||
}
|
||||
|
||||
static _T *&get_ptr_ref(const FunctorData &s) {
|
||||
return (_T *&)s;
|
||||
static T *&get_ptr_ref(const FunctorData &s) {
|
||||
return (T *&)s;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -427,16 +427,16 @@ namespace detail {
|
|||
const FunctionManager *manager;
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
static const FunctionManager &get_default_fm();
|
||||
|
||||
struct FunctionManager {
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
inline static const FunctionManager create_default_manager() {
|
||||
return FunctionManager {
|
||||
&call_move_and_destroy<_T>,
|
||||
&call_copy<_T>,
|
||||
&call_destroy<_T>
|
||||
&call_move_and_destroy<T>,
|
||||
&call_copy<T>,
|
||||
&call_destroy<T>
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -446,53 +446,53 @@ namespace detail {
|
|||
const FmStorage &rhs);
|
||||
void (* const call_destroyf)(FmStorage &s);
|
||||
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
static void call_move_and_destroy(FmStorage &lhs,
|
||||
FmStorage &&rhs) {
|
||||
typedef FunctorDataManager<_T> _spec;
|
||||
typedef FunctorDataManager<T> _spec;
|
||||
_spec::move_f(lhs.data, octa::move(rhs.data));
|
||||
_spec::destroy_f(rhs.data);
|
||||
lhs.manager = &get_default_fm<_T>();
|
||||
lhs.manager = &get_default_fm<T>();
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
static void call_copy(FmStorage &lhs,
|
||||
const FmStorage &rhs) {
|
||||
typedef FunctorDataManager<_T> _spec;
|
||||
lhs.manager = &get_default_fm<_T>();
|
||||
typedef FunctorDataManager<T> _spec;
|
||||
lhs.manager = &get_default_fm<T>();
|
||||
_spec::store_f(lhs.data, _spec::get_ref(rhs.data));
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
static void call_destroy(FmStorage &s) {
|
||||
typedef FunctorDataManager<_T> _spec;
|
||||
typedef FunctorDataManager<T> _spec;
|
||||
_spec::destroy_f(s.data);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
inline static const FunctionManager &get_default_fm() {
|
||||
static const FunctionManager def_manager
|
||||
= FunctionManager::create_default_manager<_T>();
|
||||
= FunctionManager::create_default_manager<T>();
|
||||
return def_manager;
|
||||
}
|
||||
|
||||
template<typename _R, typename...>
|
||||
template<typename R, typename...>
|
||||
struct FunctionBase {
|
||||
typedef _R Result;
|
||||
typedef R Result;
|
||||
};
|
||||
|
||||
template<typename _R, typename _T>
|
||||
struct FunctionBase<_R, _T> {
|
||||
typedef _R Result;
|
||||
typedef _T Argument;
|
||||
template<typename R, typename T>
|
||||
struct FunctionBase<R, T> {
|
||||
typedef R Result;
|
||||
typedef T Argument;
|
||||
};
|
||||
|
||||
template<typename _R, typename _T, typename _U>
|
||||
struct FunctionBase<_R, _T, _U> {
|
||||
typedef _R Result;
|
||||
typedef _T FirstArgument;
|
||||
typedef _U SecondArgument;
|
||||
template<typename R, typename T, typename U>
|
||||
struct FunctionBase<R, T, U> {
|
||||
typedef R Result;
|
||||
typedef T FirstArgument;
|
||||
typedef U SecondArgument;
|
||||
};
|
||||
|
||||
template<typename, typename>
|
||||
|
@ -500,47 +500,47 @@ namespace detail {
|
|||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template<typename _R, typename ..._A>
|
||||
struct IsValidFunctor<Function<_R(_A...)>, _R(_A...)> {
|
||||
template<typename R, typename ...A>
|
||||
struct IsValidFunctor<Function<R(A...)>, R(A...)> {
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
struct Empty {
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
_T func_to_functor(_T &&f) {
|
||||
return octa::forward<_T>(f);
|
||||
template<typename T>
|
||||
T func_to_functor(T &&f) {
|
||||
return octa::forward<T>(f);
|
||||
}
|
||||
|
||||
template<typename _RR, typename _T, typename ..._AA>
|
||||
auto func_to_functor(_RR (_T::*f)(_AA...))
|
||||
template<typename RR, typename T, typename ...AA>
|
||||
auto func_to_functor(RR (T::*f)(AA...))
|
||||
-> decltype(mem_fn(f)) {
|
||||
return mem_fn(f);
|
||||
}
|
||||
|
||||
template<typename _RR, typename _T, typename ..._AA>
|
||||
auto func_to_functor(_RR (_T::*f)(_AA...) const)
|
||||
template<typename RR, typename T, typename ...AA>
|
||||
auto func_to_functor(RR (T::*f)(AA...) const)
|
||||
-> decltype(mem_fn(f)) {
|
||||
return mem_fn(f);
|
||||
}
|
||||
|
||||
template<typename _T, typename _R, typename ..._A>
|
||||
struct IsValidFunctor<_T, _R(_A...)> {
|
||||
template<typename _U>
|
||||
static decltype(func_to_functor(octa::declval<_U>())
|
||||
(octa::declval<_A>()...)) test(_U *);
|
||||
template<typename T, typename R, typename ...A>
|
||||
struct IsValidFunctor<T, R(A...)> {
|
||||
template<typename U>
|
||||
static decltype(func_to_functor(octa::declval<U>())
|
||||
(octa::declval<A>()...)) test(U *);
|
||||
template<typename>
|
||||
static Empty test(...);
|
||||
|
||||
static constexpr bool value = octa::IsConvertible<
|
||||
decltype(test<_T>(nullptr)), _R
|
||||
decltype(test<T>(nullptr)), R
|
||||
>::value;
|
||||
};
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename _R, typename ..._A>
|
||||
struct Function<_R(_A...)>: octa::detail::FunctionBase<_R, _A...> {
|
||||
template<typename R, typename ...A>
|
||||
struct Function<R(A...)>: octa::detail::FunctionBase<R, A...> {
|
||||
Function( ) { init_empty(); }
|
||||
Function(nullptr_t) { init_empty(); }
|
||||
|
||||
|
@ -553,16 +553,16 @@ struct Function<_R(_A...)>: octa::detail::FunctionBase<_R, _A...> {
|
|||
f.p_stor.manager->call_copyf(p_stor, f.p_stor);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
Function(_T f, EnableIf<
|
||||
octa::detail::IsValidFunctor<_T, _R(_A...)>::value,
|
||||
template<typename T>
|
||||
Function(T f, EnableIf<
|
||||
octa::detail::IsValidFunctor<T, R(A...)>::value,
|
||||
octa::detail::Empty
|
||||
> = octa::detail::Empty()) {
|
||||
if (func_is_null(f)) {
|
||||
init_empty();
|
||||
return;
|
||||
}
|
||||
initialize(octa::detail::func_to_functor(octa::forward<_T>(f)));
|
||||
initialize(octa::detail::func_to_functor(octa::forward<T>(f)));
|
||||
}
|
||||
|
||||
~Function() {
|
||||
|
@ -581,8 +581,8 @@ struct Function<_R(_A...)>: octa::detail::FunctionBase<_R, _A...> {
|
|||
return *this;
|
||||
};
|
||||
|
||||
_R operator()(_A ...args) const {
|
||||
return p_call(p_stor.data, octa::forward<_A>(args)...);
|
||||
R operator()(A ...args) const {
|
||||
return p_call(p_stor.data, octa::forward<A>(args)...);
|
||||
}
|
||||
|
||||
template<typename _F> void assign(_F &&f) {
|
||||
|
@ -604,52 +604,52 @@ struct Function<_R(_A...)>: octa::detail::FunctionBase<_R, _A...> {
|
|||
|
||||
private:
|
||||
octa::detail::FmStorage p_stor;
|
||||
_R (*p_call)(const octa::detail::FunctorData &, _A...);
|
||||
R (*p_call)(const octa::detail::FunctorData &, A...);
|
||||
|
||||
template<typename _T>
|
||||
void initialize(_T f) {
|
||||
p_call = &octa::detail::FunctorDataManager<_T>::template call<_R, _A...>;
|
||||
p_stor.manager = &octa::detail::get_default_fm<_T>();
|
||||
octa::detail::FunctorDataManager<_T>::store_f(p_stor.data,
|
||||
octa::forward<_T>(f));
|
||||
template<typename T>
|
||||
void initialize(T f) {
|
||||
p_call = &octa::detail::FunctorDataManager<T>::template call<R, A...>;
|
||||
p_stor.manager = &octa::detail::get_default_fm<T>();
|
||||
octa::detail::FunctorDataManager<T>::store_f(p_stor.data,
|
||||
octa::forward<T>(f));
|
||||
}
|
||||
|
||||
void init_empty() {
|
||||
typedef _R(*emptyf)(_A...);
|
||||
typedef R(*emptyf)(A...);
|
||||
p_call = nullptr;
|
||||
p_stor.manager = &octa::detail::get_default_fm<emptyf>();
|
||||
octa::detail::FunctorDataManager<emptyf>::store_f(p_stor.data, nullptr);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
static bool func_is_null(const _T &) { return false; }
|
||||
template<typename T>
|
||||
static bool func_is_null(const T &) { return false; }
|
||||
|
||||
static bool func_is_null(_R (* const &fptr)(_A...)) {
|
||||
static bool func_is_null(R (* const &fptr)(A...)) {
|
||||
return fptr == nullptr;
|
||||
}
|
||||
|
||||
template<typename _RR, typename _T, typename ..._AA>
|
||||
static bool func_is_null(_RR (_T::* const &fptr)(_AA...)) {
|
||||
template<typename RR, typename T, typename ...AA>
|
||||
static bool func_is_null(RR (T::* const &fptr)(AA...)) {
|
||||
return fptr == nullptr;
|
||||
}
|
||||
|
||||
template<typename _RR, typename _T, typename ..._AA>
|
||||
static bool func_is_null(_RR (_T::* const &fptr)(_AA...) const) {
|
||||
template<typename RR, typename T, typename ...AA>
|
||||
static bool func_is_null(RR (T::* const &fptr)(AA...) const) {
|
||||
return fptr == nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
bool operator==(nullptr_t, const Function<_T> &rhs) { return !rhs; }
|
||||
template<typename T>
|
||||
bool operator==(nullptr_t, const Function<T> &rhs) { return !rhs; }
|
||||
|
||||
template<typename _T>
|
||||
bool operator==(const Function<_T> &lhs, nullptr_t) { return !lhs; }
|
||||
template<typename T>
|
||||
bool operator==(const Function<T> &lhs, nullptr_t) { return !lhs; }
|
||||
|
||||
template<typename _T>
|
||||
bool operator!=(nullptr_t, const Function<_T> &rhs) { return rhs; }
|
||||
template<typename T>
|
||||
bool operator!=(nullptr_t, const Function<T> &rhs) { return rhs; }
|
||||
|
||||
template<typename _T>
|
||||
bool operator!=(const Function<_T> &lhs, nullptr_t) { return lhs; }
|
||||
template<typename T>
|
||||
bool operator!=(const Function<T> &lhs, nullptr_t) { return lhs; }
|
||||
|
||||
} /* namespace octa */
|
||||
|
||||
|
|
|
@ -14,19 +14,19 @@
|
|||
/* must be in std namespace otherwise the compiler won't know about it */
|
||||
namespace std {
|
||||
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
class initializer_list {
|
||||
const _T *p_buf;
|
||||
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): p_buf(v), p_len(n) {}
|
||||
public:
|
||||
initializer_list(): p_buf(nullptr), p_len(0) {}
|
||||
|
||||
size_t size() const { return p_len; }
|
||||
|
||||
const _T *begin() const { return p_buf; }
|
||||
const _T *end() const { return p_buf + p_len; }
|
||||
const T *begin() const { return p_buf; }
|
||||
const T *end() const { return p_buf + p_len; }
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -36,11 +36,11 @@ public:
|
|||
|
||||
namespace octa {
|
||||
|
||||
template<typename _T> using InitializerList = std::initializer_list<_T>;
|
||||
template<typename T> using InitializerList = std::initializer_list<T>;
|
||||
|
||||
template<typename _T>
|
||||
octa::PointerRange<const _T> each(std::initializer_list<_T> init) {
|
||||
return octa::PointerRange<const _T>(init.begin(), init.end());
|
||||
template<typename T>
|
||||
octa::PointerRange<const T> each(std::initializer_list<T> init) {
|
||||
return octa::PointerRange<const T>(init.begin(), init.end());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
918
octa/memory.h
918
octa/memory.h
File diff suppressed because it is too large
Load Diff
528
octa/range.h
528
octa/range.h
|
@ -21,21 +21,21 @@ struct BidirectionalRangeTag: ForwardRangeTag {};
|
|||
struct RandomAccessRangeTag: BidirectionalRangeTag {};
|
||||
struct FiniteRandomAccessRangeTag: RandomAccessRangeTag {};
|
||||
|
||||
template<typename _T> struct RangeHalf;
|
||||
template<typename T> struct RangeHalf;
|
||||
|
||||
#define OCTA_RANGE_TRAIT(_Name, _TypeName) \
|
||||
#define OCTA_RANGE_TRAIT(Name, TypeName) \
|
||||
namespace detail { \
|
||||
template<typename _T> \
|
||||
struct Range##_Name##Base { \
|
||||
typedef typename _T::_TypeName Type; \
|
||||
template<typename T> \
|
||||
struct Range##Name##Base { \
|
||||
typedef typename T::TypeName Type; \
|
||||
}; \
|
||||
template<typename _T> \
|
||||
struct Range##_Name##Base<RangeHalf<_T>> { \
|
||||
typedef typename _T::_TypeName Type; \
|
||||
template<typename T> \
|
||||
struct Range##Name##Base<RangeHalf<T>> { \
|
||||
typedef typename T::TypeName Type; \
|
||||
}; \
|
||||
} \
|
||||
template<typename _T> \
|
||||
using Range##_Name = typename octa::detail::Range##_Name##Base<_T>::Type;
|
||||
template<typename T> \
|
||||
using Range##Name = typename octa::detail::Range##Name##Base<T>::Type;
|
||||
|
||||
OCTA_RANGE_TRAIT(Category, Category)
|
||||
OCTA_RANGE_TRAIT(Size, Size)
|
||||
|
@ -47,109 +47,109 @@ OCTA_RANGE_TRAIT(Difference, Difference)
|
|||
|
||||
// is input range
|
||||
|
||||
template<typename _T, bool = octa::IsConvertible<
|
||||
RangeCategory<_T>, InputRangeTag
|
||||
template<typename T, bool = octa::IsConvertible<
|
||||
RangeCategory<T>, InputRangeTag
|
||||
>::value> struct IsInputRange: False {};
|
||||
|
||||
template<typename _T>
|
||||
struct IsInputRange<_T, true>: True {};
|
||||
template<typename T>
|
||||
struct IsInputRange<T, true>: True {};
|
||||
|
||||
// is forward range
|
||||
|
||||
template<typename _T, bool = octa::IsConvertible<
|
||||
RangeCategory<_T>, ForwardRangeTag
|
||||
template<typename T, bool = octa::IsConvertible<
|
||||
RangeCategory<T>, ForwardRangeTag
|
||||
>::value> struct IsForwardRange: False {};
|
||||
|
||||
template<typename _T>
|
||||
struct IsForwardRange<_T, true>: True {};
|
||||
template<typename T>
|
||||
struct IsForwardRange<T, true>: True {};
|
||||
|
||||
// is bidirectional range
|
||||
|
||||
template<typename _T, bool = octa::IsConvertible<
|
||||
RangeCategory<_T>, BidirectionalRangeTag
|
||||
template<typename T, bool = octa::IsConvertible<
|
||||
RangeCategory<T>, BidirectionalRangeTag
|
||||
>::value> struct IsBidirectionalRange: False {};
|
||||
|
||||
template<typename _T>
|
||||
struct IsBidirectionalRange<_T, true>: True {};
|
||||
template<typename T>
|
||||
struct IsBidirectionalRange<T, true>: True {};
|
||||
|
||||
// is random access range
|
||||
|
||||
template<typename _T, bool = octa::IsConvertible<
|
||||
RangeCategory<_T>, RandomAccessRangeTag
|
||||
template<typename T, bool = octa::IsConvertible<
|
||||
RangeCategory<T>, RandomAccessRangeTag
|
||||
>::value> struct IsRandomAccessRange: False {};
|
||||
|
||||
template<typename _T>
|
||||
struct IsRandomAccessRange<_T, true>: True {};
|
||||
template<typename T>
|
||||
struct IsRandomAccessRange<T, true>: True {};
|
||||
|
||||
// is finite random access range
|
||||
|
||||
template<typename _T, bool = octa::IsConvertible<
|
||||
RangeCategory<_T>, FiniteRandomAccessRangeTag
|
||||
template<typename T, bool = octa::IsConvertible<
|
||||
RangeCategory<T>, FiniteRandomAccessRangeTag
|
||||
>::value> struct IsFiniteRandomAccessRange: False {};
|
||||
|
||||
template<typename _T>
|
||||
struct IsFiniteRandomAccessRange<_T, true>: True {};
|
||||
template<typename T>
|
||||
struct IsFiniteRandomAccessRange<T, true>: True {};
|
||||
|
||||
// is infinite random access range
|
||||
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
struct IsInfiniteRandomAccessRange: IntegralConstant<bool,
|
||||
(IsRandomAccessRange<_T>::value && !IsFiniteRandomAccessRange<_T>::value)
|
||||
(IsRandomAccessRange<T>::value && !IsFiniteRandomAccessRange<T>::value)
|
||||
> {};
|
||||
|
||||
// is output range
|
||||
|
||||
namespace detail {
|
||||
template<typename _T, typename _P>
|
||||
template<typename T, typename P>
|
||||
struct OutputRangeTest {
|
||||
template<typename _U, void (_U::*)(_P)> struct Test {};
|
||||
template<typename _U> static char test(Test<_U, &_U::put> *);
|
||||
template<typename _U> static int test(...);
|
||||
static constexpr bool value = (sizeof(test<_T>(0)) == sizeof(char));
|
||||
template<typename U, void (U::*)(P)> struct Test {};
|
||||
template<typename U> static char test(Test<U, &U::put> *);
|
||||
template<typename U> static int test(...);
|
||||
static constexpr bool value = (sizeof(test<T>(0)) == sizeof(char));
|
||||
};
|
||||
}
|
||||
|
||||
template<typename _T, bool = (octa::IsConvertible<
|
||||
RangeCategory<_T>, OutputRangeTag
|
||||
>::value || (IsInputRange<_T>::value &&
|
||||
(octa::detail::OutputRangeTest<_T, const RangeValue<_T> &>::value ||
|
||||
octa::detail::OutputRangeTest<_T, RangeValue<_T> &&>::value)
|
||||
template<typename T, bool = (octa::IsConvertible<
|
||||
RangeCategory<T>, OutputRangeTag
|
||||
>::value || (IsInputRange<T>::value &&
|
||||
(octa::detail::OutputRangeTest<T, const RangeValue<T> &>::value ||
|
||||
octa::detail::OutputRangeTest<T, RangeValue<T> &&>::value)
|
||||
))> struct IsOutputRange: False {};
|
||||
|
||||
template<typename _T>
|
||||
struct IsOutputRange<_T, true>: True {};
|
||||
template<typename T>
|
||||
struct IsOutputRange<T, true>: True {};
|
||||
|
||||
namespace detail {
|
||||
// range iterator
|
||||
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
struct RangeIterator {
|
||||
RangeIterator(): p_range() {}
|
||||
explicit RangeIterator(const _T &range): p_range(range) {}
|
||||
explicit RangeIterator(const T &range): p_range(range) {}
|
||||
RangeIterator &operator++() {
|
||||
p_range.pop_front();
|
||||
return *this;
|
||||
}
|
||||
RangeReference<_T> operator*() const {
|
||||
RangeReference<T> operator*() const {
|
||||
return p_range.front();
|
||||
}
|
||||
bool operator!=(RangeIterator) const { return !p_range.empty(); }
|
||||
private:
|
||||
_T p_range;
|
||||
T p_range;
|
||||
};
|
||||
}
|
||||
|
||||
// range half
|
||||
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
struct RangeHalf {
|
||||
private:
|
||||
_T p_range;
|
||||
T p_range;
|
||||
public:
|
||||
typedef _T Range;
|
||||
typedef T Range;
|
||||
|
||||
RangeHalf(): p_range() {}
|
||||
RangeHalf(const _T &range): p_range(range) {}
|
||||
RangeHalf(const T &range): p_range(range) {}
|
||||
RangeHalf(const RangeHalf &half): p_range(half.p_range) {}
|
||||
RangeHalf(RangeHalf &&half): p_range(octa::move(half.p_range)) {}
|
||||
|
||||
|
@ -163,23 +163,23 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
_T range() const { return p_range; }
|
||||
T range() const { return p_range; }
|
||||
|
||||
bool next() { return p_range.pop_front(); }
|
||||
bool prev() { return p_range.push_front(); }
|
||||
|
||||
RangeSize<_T> next_n(RangeSize<_T> n) {
|
||||
RangeSize<T> next_n(RangeSize<T> n) {
|
||||
return p_range.pop_front_n(n);
|
||||
}
|
||||
RangeSize<_T> prev_n(RangeSize<_T> n) {
|
||||
RangeSize<T> prev_n(RangeSize<T> n) {
|
||||
return p_range.push_front_n(n);
|
||||
}
|
||||
|
||||
RangeReference<_T> get() const {
|
||||
RangeReference<T> get() const {
|
||||
return p_range.front();
|
||||
}
|
||||
|
||||
RangeDifference<_T> distance(const RangeHalf &half) const {
|
||||
RangeDifference<T> distance(const RangeHalf &half) const {
|
||||
return p_range.distance_front(half.p_range);
|
||||
}
|
||||
|
||||
|
@ -196,11 +196,11 @@ public:
|
|||
|
||||
/* iterator like interface */
|
||||
|
||||
RangeReference<_T> operator*() const {
|
||||
RangeReference<T> operator*() const {
|
||||
return get();
|
||||
}
|
||||
|
||||
RangeReference<_T> operator[](RangeSize<_T> idx) const {
|
||||
RangeReference<T> operator[](RangeSize<T> idx) const {
|
||||
return p_range[idx];
|
||||
}
|
||||
|
||||
|
@ -224,132 +224,132 @@ public:
|
|||
return octa::move(tmp);
|
||||
}
|
||||
|
||||
RangeHalf operator+(RangeDifference<_T> n) {
|
||||
RangeHalf operator+(RangeDifference<T> n) {
|
||||
RangeHalf tmp(*this);
|
||||
if (n < 0) tmp.prev_n(-n);
|
||||
else tmp.next_n(n);
|
||||
return octa::move(tmp);
|
||||
}
|
||||
RangeHalf operator-(RangeDifference<_T> n) {
|
||||
RangeHalf operator-(RangeDifference<T> n) {
|
||||
RangeHalf tmp(*this);
|
||||
if (n < 0) tmp.next_n(-n);
|
||||
else tmp.prev_n(n);
|
||||
return octa::move(tmp);
|
||||
}
|
||||
|
||||
RangeHalf &operator+=(RangeDifference<_T> n) {
|
||||
RangeHalf &operator+=(RangeDifference<T> n) {
|
||||
if (n < 0) prev_n(-n);
|
||||
else next_n(n);
|
||||
return *this;
|
||||
}
|
||||
RangeHalf &operator-=(RangeDifference<_T> n) {
|
||||
RangeHalf &operator-=(RangeDifference<T> n) {
|
||||
if (n < 0) next_n(-n);
|
||||
else prev_n(n);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _R>
|
||||
RangeDifference<_R> operator-(const _R &lhs, const _R &rhs) {
|
||||
template<typename R>
|
||||
RangeDifference<R> operator-(const R &lhs, const R &rhs) {
|
||||
return rhs.distance(lhs);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename _R>
|
||||
RangeSize<_R> pop_front_n(_R &range, RangeSize<_R> n) {
|
||||
for (RangeSize<_R> i = 0; i < n; ++i)
|
||||
template<typename R>
|
||||
RangeSize<R> pop_front_n(R &range, RangeSize<R> n) {
|
||||
for (RangeSize<R> i = 0; i < n; ++i)
|
||||
if (!range.pop_front()) return i;
|
||||
return n;
|
||||
}
|
||||
|
||||
template<typename _R>
|
||||
RangeSize<_R> pop_back_n(_R &range, RangeSize<_R> n) {
|
||||
for (RangeSize<_R> i = 0; i < n; ++i)
|
||||
template<typename R>
|
||||
RangeSize<R> pop_back_n(R &range, RangeSize<R> n) {
|
||||
for (RangeSize<R> i = 0; i < n; ++i)
|
||||
if (!range.pop_back()) return i;
|
||||
return n;
|
||||
}
|
||||
|
||||
template<typename _R>
|
||||
RangeSize<_R> push_front_n(_R &range, RangeSize<_R> n) {
|
||||
for (RangeSize<_R> i = 0; i < n; ++i)
|
||||
template<typename R>
|
||||
RangeSize<R> push_front_n(R &range, RangeSize<R> n) {
|
||||
for (RangeSize<R> i = 0; i < n; ++i)
|
||||
if (!range.push_front()) return i;
|
||||
return n;
|
||||
}
|
||||
|
||||
template<typename _R>
|
||||
RangeSize<_R> push_back_n(_R &range, RangeSize<_R> n) {
|
||||
for (RangeSize<_R> i = 0; i < n; ++i)
|
||||
template<typename R>
|
||||
RangeSize<R> push_back_n(R &range, RangeSize<R> n) {
|
||||
for (RangeSize<R> i = 0; i < n; ++i)
|
||||
if (!range.push_back()) return i;
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _B, typename _C, typename _V, typename _R = _V &,
|
||||
typename _S = size_t, typename _D = ptrdiff_t
|
||||
template<typename B, typename C, typename V, typename R = V &,
|
||||
typename S = size_t, typename D = ptrdiff_t
|
||||
> struct InputRange {
|
||||
typedef _C Category;
|
||||
typedef _S Size;
|
||||
typedef _D Difference;
|
||||
typedef _V Value;
|
||||
typedef _R Reference;
|
||||
typedef C Category;
|
||||
typedef S Size;
|
||||
typedef D Difference;
|
||||
typedef V Value;
|
||||
typedef R Reference;
|
||||
|
||||
octa::detail::RangeIterator<_B> begin() const {
|
||||
return octa::detail::RangeIterator<_B>((const _B &)*this);
|
||||
octa::detail::RangeIterator<B> begin() const {
|
||||
return octa::detail::RangeIterator<B>((const B &)*this);
|
||||
}
|
||||
octa::detail::RangeIterator<_B> end() const {
|
||||
return octa::detail::RangeIterator<_B>();
|
||||
octa::detail::RangeIterator<B> end() const {
|
||||
return octa::detail::RangeIterator<B>();
|
||||
}
|
||||
|
||||
Size pop_front_n(Size n) {
|
||||
return octa::detail::pop_front_n<_B>(*((_B *)this), n);
|
||||
return octa::detail::pop_front_n<B>(*((B *)this), n);
|
||||
}
|
||||
|
||||
Size pop_back_n(Size n) {
|
||||
return octa::detail::pop_back_n<_B>(*((_B *)this), n);
|
||||
return octa::detail::pop_back_n<B>(*((B *)this), n);
|
||||
}
|
||||
|
||||
Size push_front_n(Size n) {
|
||||
return octa::detail::push_front_n<_B>(*((_B *)this), n);
|
||||
return octa::detail::push_front_n<B>(*((B *)this), n);
|
||||
}
|
||||
|
||||
Size push_back_n(Size n) {
|
||||
return octa::detail::push_back_n<_B>(*((_B *)this), n);
|
||||
return octa::detail::push_back_n<B>(*((B *)this), n);
|
||||
}
|
||||
|
||||
_B each() const {
|
||||
return _B(*((_B *)this));
|
||||
B each() const {
|
||||
return B(*((B *)this));
|
||||
}
|
||||
|
||||
RangeHalf<_B> half() const {
|
||||
return RangeHalf<_B>(*((_B *)this));
|
||||
RangeHalf<B> half() const {
|
||||
return RangeHalf<B>(*((B *)this));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _V, typename _R = _V &, typename _S = size_t,
|
||||
typename _D = ptrdiff_t
|
||||
template<typename V, typename R = V &, typename S = size_t,
|
||||
typename D = ptrdiff_t
|
||||
> struct OutputRange {
|
||||
typedef OutputRangeTag Category;
|
||||
typedef _S Size;
|
||||
typedef _D Difference;
|
||||
typedef _V Value;
|
||||
typedef _R Reference;
|
||||
typedef S Size;
|
||||
typedef D Difference;
|
||||
typedef V Value;
|
||||
typedef R Reference;
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
struct ReverseRange: InputRange<ReverseRange<_T>,
|
||||
RangeCategory<_T>, RangeValue<_T>, RangeReference<_T>, RangeSize<_T>,
|
||||
RangeDifference<_T>
|
||||
template<typename T>
|
||||
struct ReverseRange: InputRange<ReverseRange<T>,
|
||||
RangeCategory<T>, RangeValue<T>, RangeReference<T>, RangeSize<T>,
|
||||
RangeDifference<T>
|
||||
> {
|
||||
private:
|
||||
typedef RangeReference<_T> _r_ref;
|
||||
typedef RangeSize<_T> _r_size;
|
||||
typedef RangeReference<T> r_ref;
|
||||
typedef RangeSize<T> r_size;
|
||||
|
||||
_T p_range;
|
||||
T p_range;
|
||||
|
||||
public:
|
||||
ReverseRange(): p_range() {}
|
||||
|
||||
ReverseRange(const _T &range): p_range(range) {}
|
||||
ReverseRange(const T &range): p_range(range) {}
|
||||
|
||||
ReverseRange(const ReverseRange &it): p_range(it.p_range) {}
|
||||
|
||||
|
@ -363,17 +363,17 @@ public:
|
|||
p_range = octa::move(v.p_range);
|
||||
return *this;
|
||||
}
|
||||
ReverseRange &operator=(const _T &v) {
|
||||
ReverseRange &operator=(const T &v) {
|
||||
p_range = v;
|
||||
return *this;
|
||||
}
|
||||
ReverseRange &operator=(_T &&v) {
|
||||
ReverseRange &operator=(T &&v) {
|
||||
p_range = octa::move(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const { return p_range.empty(); }
|
||||
_r_size size() const { return p_range.size(); }
|
||||
r_size size() const { return p_range.size(); }
|
||||
|
||||
bool equals_front(const ReverseRange &r) const {
|
||||
return p_range.equals_back(r.p_range);
|
||||
|
@ -382,10 +382,10 @@ public:
|
|||
return p_range.equals_front(r.p_range);
|
||||
}
|
||||
|
||||
RangeDifference<_T> distance_front(const ReverseRange &r) const {
|
||||
RangeDifference<T> distance_front(const ReverseRange &r) const {
|
||||
return -p_range.distance_back(r.p_range);
|
||||
}
|
||||
RangeDifference<_T> distance_back(const ReverseRange &r) const {
|
||||
RangeDifference<T> distance_back(const ReverseRange &r) const {
|
||||
return -p_range.distance_front(r.p_range);
|
||||
}
|
||||
|
||||
|
@ -395,44 +395,44 @@ public:
|
|||
bool push_front() { return p_range.push_back(); }
|
||||
bool push_back() { return p_range.push_front(); }
|
||||
|
||||
_r_size pop_front_n(_r_size n) { return p_range.pop_front_n(n); }
|
||||
_r_size pop_back_n(_r_size n) { return p_range.pop_back_n(n); }
|
||||
r_size pop_front_n(r_size n) { return p_range.pop_front_n(n); }
|
||||
r_size pop_back_n(r_size n) { return p_range.pop_back_n(n); }
|
||||
|
||||
_r_size push_front_n(_r_size n) { return p_range.push_front_n(n); }
|
||||
_r_size push_back_n(_r_size n) { return p_range.push_back_n(n); }
|
||||
r_size push_front_n(r_size n) { return p_range.push_front_n(n); }
|
||||
r_size push_back_n(r_size n) { return p_range.push_back_n(n); }
|
||||
|
||||
_r_ref front() const { return p_range.back(); }
|
||||
_r_ref back() const { return p_range.front(); }
|
||||
r_ref front() const { return p_range.back(); }
|
||||
r_ref back() const { return p_range.front(); }
|
||||
|
||||
_r_ref operator[](_r_size i) const { return p_range[size() - i - 1]; }
|
||||
r_ref operator[](r_size i) const { return p_range[size() - i - 1]; }
|
||||
|
||||
ReverseRange<_T> slice(_r_size start, _r_size end) const {
|
||||
_r_size len = p_range.size();
|
||||
return ReverseRange<_T>(p_range.slice(len - end, len - start));
|
||||
ReverseRange<T> slice(r_size start, r_size end) const {
|
||||
r_size len = p_range.size();
|
||||
return ReverseRange<T>(p_range.slice(len - end, len - start));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
ReverseRange<_T> make_reverse_range(const _T &it) {
|
||||
return ReverseRange<_T>(it);
|
||||
template<typename T>
|
||||
ReverseRange<T> make_reverse_range(const T &it) {
|
||||
return ReverseRange<T>(it);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
struct MoveRange: InputRange<MoveRange<_T>,
|
||||
RangeCategory<_T>, RangeValue<_T>, RangeValue<_T> &&, RangeSize<_T>,
|
||||
RangeDifference<_T>
|
||||
template<typename T>
|
||||
struct MoveRange: InputRange<MoveRange<T>,
|
||||
RangeCategory<T>, RangeValue<T>, RangeValue<T> &&, RangeSize<T>,
|
||||
RangeDifference<T>
|
||||
> {
|
||||
private:
|
||||
typedef RangeValue<_T> _r_val;
|
||||
typedef RangeValue<_T> &&_r_ref;
|
||||
typedef RangeSize<_T> _r_size;
|
||||
typedef RangeValue<T> r_val;
|
||||
typedef RangeValue<T> &&r_ref;
|
||||
typedef RangeSize<T> r_size;
|
||||
|
||||
_T p_range;
|
||||
T p_range;
|
||||
|
||||
public:
|
||||
MoveRange(): p_range() {}
|
||||
|
||||
MoveRange(const _T &range): p_range(range) {}
|
||||
MoveRange(const T &range): p_range(range) {}
|
||||
|
||||
MoveRange(const MoveRange &it): p_range(it.p_range) {}
|
||||
|
||||
|
@ -446,17 +446,17 @@ public:
|
|||
p_range = octa::move(v.p_range);
|
||||
return *this;
|
||||
}
|
||||
MoveRange &operator=(const _T &v) {
|
||||
MoveRange &operator=(const T &v) {
|
||||
p_range = v;
|
||||
return *this;
|
||||
}
|
||||
MoveRange &operator=(_T &&v) {
|
||||
MoveRange &operator=(T &&v) {
|
||||
p_range = octa::move(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const { return p_range.empty(); }
|
||||
_r_size size() const { return p_range.size(); }
|
||||
r_size size() const { return p_range.size(); }
|
||||
|
||||
bool equals_front(const MoveRange &r) const {
|
||||
return p_range.equals_front(r.p_range);
|
||||
|
@ -465,10 +465,10 @@ public:
|
|||
return p_range.equals_back(r.p_range);
|
||||
}
|
||||
|
||||
RangeDifference<_T> distance_front(const MoveRange &r) const {
|
||||
RangeDifference<T> distance_front(const MoveRange &r) const {
|
||||
return p_range.distance_front(r.p_range);
|
||||
}
|
||||
RangeDifference<_T> distance_back(const MoveRange &r) const {
|
||||
RangeDifference<T> distance_back(const MoveRange &r) const {
|
||||
return p_range.distance_back(r.p_range);
|
||||
}
|
||||
|
||||
|
@ -478,38 +478,38 @@ public:
|
|||
bool push_front() { return p_range.push_front(); }
|
||||
bool push_back() { return p_range.push_back(); }
|
||||
|
||||
_r_size pop_front_n(_r_size n) { return p_range.pop_front_n(n); }
|
||||
_r_size pop_back_n(_r_size n) { return p_range.pop_back_n(n); }
|
||||
r_size pop_front_n(r_size n) { return p_range.pop_front_n(n); }
|
||||
r_size pop_back_n(r_size n) { return p_range.pop_back_n(n); }
|
||||
|
||||
_r_size push_front_n(_r_size n) { return p_range.push_front_n(n); }
|
||||
_r_size push_back_n(_r_size n) { return p_range.push_back_n(n); }
|
||||
r_size push_front_n(r_size n) { return p_range.push_front_n(n); }
|
||||
r_size push_back_n(r_size n) { return p_range.push_back_n(n); }
|
||||
|
||||
_r_ref front() const { return octa::move(p_range.front()); }
|
||||
_r_ref back() const { return octa::move(p_range.back()); }
|
||||
r_ref front() const { return octa::move(p_range.front()); }
|
||||
r_ref back() const { return octa::move(p_range.back()); }
|
||||
|
||||
_r_ref operator[](_r_size i) const { return octa::move(p_range[i]); }
|
||||
r_ref operator[](r_size i) const { return octa::move(p_range[i]); }
|
||||
|
||||
MoveRange<_T> slice(_r_size start, _r_size end) const {
|
||||
return MoveRange<_T>(p_range.slice(start, end));
|
||||
MoveRange<T> slice(r_size start, r_size end) const {
|
||||
return MoveRange<T>(p_range.slice(start, end));
|
||||
}
|
||||
|
||||
void put(const _r_val &v) { p_range.put(v); }
|
||||
void put(_r_val &&v) { p_range.put(octa::move(v)); }
|
||||
void put(const r_val &v) { p_range.put(v); }
|
||||
void put(r_val &&v) { p_range.put(octa::move(v)); }
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
MoveRange<_T> make_move_range(const _T &it) {
|
||||
return MoveRange<_T>(it);
|
||||
template<typename T>
|
||||
MoveRange<T> make_move_range(const T &it) {
|
||||
return MoveRange<T>(it);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
struct NumberRange: InputRange<NumberRange<_T>, ForwardRangeTag, _T, _T> {
|
||||
template<typename T>
|
||||
struct NumberRange: InputRange<NumberRange<T>, ForwardRangeTag, T, 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),
|
||||
p_step(it.p_step) {}
|
||||
NumberRange(_T a, _T b, _T step = _T(1)): p_a(a), p_b(b),
|
||||
NumberRange(T a, T b, T step = T(1)): p_a(a), p_b(b),
|
||||
p_step(step) {}
|
||||
NumberRange(_T v): p_a(0), p_b(v), p_step(1) {}
|
||||
NumberRange(T v): p_a(0), p_b(v), p_step(1) {}
|
||||
|
||||
bool empty() const { return p_a * p_step >= p_b * p_step; }
|
||||
|
||||
|
@ -519,29 +519,29 @@ struct NumberRange: InputRange<NumberRange<_T>, ForwardRangeTag, _T, _T> {
|
|||
|
||||
bool pop_front() { p_a += p_step; return true; }
|
||||
bool push_front() { p_a -= p_step; return true; }
|
||||
_T front() const { return p_a; }
|
||||
T front() const { return p_a; }
|
||||
|
||||
private:
|
||||
_T p_a, p_b, p_step;
|
||||
T p_a, p_b, p_step;
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
NumberRange<_T> range(_T a, _T b, _T step = _T(1)) {
|
||||
return NumberRange<_T>(a, b, step);
|
||||
template<typename T>
|
||||
NumberRange<T> range(T a, T b, T step = T(1)) {
|
||||
return NumberRange<T>(a, b, step);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
NumberRange<_T> range(_T v) {
|
||||
return NumberRange<_T>(v);
|
||||
template<typename T>
|
||||
NumberRange<T> range(T v) {
|
||||
return NumberRange<T>(v);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
struct PointerRange: InputRange<PointerRange<_T>, FiniteRandomAccessRangeTag, _T> {
|
||||
template<typename T>
|
||||
struct PointerRange: InputRange<PointerRange<T>, FiniteRandomAccessRangeTag, 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(T *beg, T *end): p_beg(beg), p_end(end) {}
|
||||
PointerRange(T *beg, size_t n): p_beg(beg), p_end(beg + n) {}
|
||||
|
||||
PointerRange &operator=(const PointerRange &v) {
|
||||
p_beg = v.p_beg;
|
||||
|
@ -575,7 +575,7 @@ struct PointerRange: InputRange<PointerRange<_T>, FiniteRandomAccessRangeTag, _T
|
|||
p_beg -= n; return true;
|
||||
}
|
||||
|
||||
_T &front() const { return *p_beg; }
|
||||
T &front() const { return *p_beg; }
|
||||
|
||||
bool equals_front(const PointerRange &range) const {
|
||||
return p_beg == range.p_beg;
|
||||
|
@ -609,7 +609,7 @@ struct PointerRange: InputRange<PointerRange<_T>, FiniteRandomAccessRangeTag, _T
|
|||
p_end += n; return true;
|
||||
}
|
||||
|
||||
_T &back() const { return *(p_end - 1); }
|
||||
T &back() const { return *(p_end - 1); }
|
||||
|
||||
bool equals_back(const PointerRange &range) const {
|
||||
return p_end == range.p_end;
|
||||
|
@ -626,43 +626,43 @@ struct PointerRange: InputRange<PointerRange<_T>, FiniteRandomAccessRangeTag, _T
|
|||
return PointerRange(p_beg + start, p_beg + end);
|
||||
}
|
||||
|
||||
_T &operator[](size_t i) const { return p_beg[i]; }
|
||||
T &operator[](size_t i) const { return p_beg[i]; }
|
||||
|
||||
/* satisfy OutputRange */
|
||||
void put(const _T &v) {
|
||||
void put(const T &v) {
|
||||
*(p_beg++) = v;
|
||||
}
|
||||
void put(_T &&v) {
|
||||
void put(T &&v) {
|
||||
*(p_beg++) = octa::move(v);
|
||||
}
|
||||
|
||||
private:
|
||||
_T *p_beg, *p_end;
|
||||
T *p_beg, *p_end;
|
||||
};
|
||||
|
||||
template<typename _T, typename _S>
|
||||
template<typename T, typename S>
|
||||
struct EnumeratedValue {
|
||||
_S index;
|
||||
_T value;
|
||||
S index;
|
||||
T value;
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
struct EnumeratedRange: InputRange<EnumeratedRange<_T>,
|
||||
CommonType<RangeCategory<_T>, ForwardRangeTag>, RangeValue<_T>,
|
||||
EnumeratedValue<RangeReference<_T>, RangeSize<_T>>,
|
||||
RangeSize<_T>
|
||||
template<typename T>
|
||||
struct EnumeratedRange: InputRange<EnumeratedRange<T>,
|
||||
CommonType<RangeCategory<T>, ForwardRangeTag>, RangeValue<T>,
|
||||
EnumeratedValue<RangeReference<T>, RangeSize<T>>,
|
||||
RangeSize<T>
|
||||
> {
|
||||
private:
|
||||
typedef RangeReference<_T> _r_ref;
|
||||
typedef RangeSize<_T> _r_size;
|
||||
typedef RangeReference<T> r_ref;
|
||||
typedef RangeSize<T> r_size;
|
||||
|
||||
_T p_range;
|
||||
_r_size p_index;
|
||||
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 T &range): p_range(range), p_index(0) {}
|
||||
|
||||
EnumeratedRange(const EnumeratedRange &it):
|
||||
p_range(it.p_range), p_index(it.p_index) {}
|
||||
|
@ -680,12 +680,12 @@ public:
|
|||
p_index = v.p_index;
|
||||
return *this;
|
||||
}
|
||||
EnumeratedRange &operator=(const _T &v) {
|
||||
EnumeratedRange &operator=(const T &v) {
|
||||
p_range = v;
|
||||
p_index = 0;
|
||||
return *this;
|
||||
}
|
||||
EnumeratedRange &operator=(_T &&v) {
|
||||
EnumeratedRange &operator=(T &&v) {
|
||||
p_range = octa::move(v);
|
||||
p_index = 0;
|
||||
return *this;
|
||||
|
@ -705,33 +705,33 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
_r_size pop_front_n(_r_size n) {
|
||||
_r_size ret = p_range.pop_front_n(n);
|
||||
r_size pop_front_n(r_size n) {
|
||||
r_size ret = p_range.pop_front_n(n);
|
||||
p_index += ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
EnumeratedValue<_r_ref, _r_size> front() const {
|
||||
return EnumeratedValue<_r_ref, _r_size> { p_index, p_range.front() };
|
||||
EnumeratedValue<r_ref, r_size> front() const {
|
||||
return EnumeratedValue<r_ref, r_size> { p_index, p_range.front() };
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
EnumeratedRange<_T> enumerate(const _T &it) {
|
||||
return EnumeratedRange<_T>(it);
|
||||
template<typename T>
|
||||
EnumeratedRange<T> enumerate(const T &it) {
|
||||
return EnumeratedRange<T>(it);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
struct TakeRange: InputRange<TakeRange<_T>,
|
||||
CommonType<RangeCategory<_T>, ForwardRangeTag>,
|
||||
RangeValue<_T>, RangeReference<_T>, RangeSize<_T>
|
||||
template<typename T>
|
||||
struct TakeRange: InputRange<TakeRange<T>,
|
||||
CommonType<RangeCategory<T>, ForwardRangeTag>,
|
||||
RangeValue<T>, RangeReference<T>, RangeSize<T>
|
||||
> {
|
||||
private:
|
||||
_T p_range;
|
||||
RangeSize<_T> p_remaining;
|
||||
T p_range;
|
||||
RangeSize<T> p_remaining;
|
||||
public:
|
||||
TakeRange(): p_range(), p_remaining(0) {}
|
||||
TakeRange(const _T &range, RangeSize<_T> rem): p_range(range),
|
||||
TakeRange(const T &range, RangeSize<T> rem): p_range(range),
|
||||
p_remaining(rem) {}
|
||||
TakeRange(const TakeRange &it): p_range(it.p_range),
|
||||
p_remaining(it.p_remaining) {}
|
||||
|
@ -764,44 +764,44 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
RangeSize<_T> pop_front_n(RangeSize<_T> n) {
|
||||
RangeSize<_T> ret = p_range.pop_front_n(n);
|
||||
RangeSize<T> pop_front_n(RangeSize<T> n) {
|
||||
RangeSize<T> ret = p_range.pop_front_n(n);
|
||||
p_remaining -= ret;
|
||||
return ret;
|
||||
}
|
||||
RangeSize<_T> push_front_n(RangeSize<_T> n) {
|
||||
RangeSize<_T> ret = p_range.push_front_n(n);
|
||||
RangeSize<T> push_front_n(RangeSize<T> n) {
|
||||
RangeSize<T> ret = p_range.push_front_n(n);
|
||||
p_remaining += ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
RangeReference<_T> front() const { return p_range.front(); }
|
||||
RangeReference<T> front() const { return p_range.front(); }
|
||||
|
||||
bool equals_front(const TakeRange &r) const {
|
||||
return p_range.equals_front(r.p_range);
|
||||
}
|
||||
|
||||
RangeDifference<_T> distance_front(const TakeRange &r) const {
|
||||
RangeDifference<T> distance_front(const TakeRange &r) const {
|
||||
return p_range.distance_front(r.p_range);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
TakeRange<_T> take(const _T &it, RangeSize<_T> n) {
|
||||
return TakeRange<_T>(it, n);
|
||||
template<typename T>
|
||||
TakeRange<T> take(const T &it, RangeSize<T> n) {
|
||||
return TakeRange<T>(it, n);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
struct ChunksRange: InputRange<ChunksRange<_T>,
|
||||
CommonType<RangeCategory<_T>, ForwardRangeTag>,
|
||||
TakeRange<_T>, TakeRange<_T>, RangeSize<_T>
|
||||
template<typename T>
|
||||
struct ChunksRange: InputRange<ChunksRange<T>,
|
||||
CommonType<RangeCategory<T>, ForwardRangeTag>,
|
||||
TakeRange<T>, TakeRange<T>, RangeSize<T>
|
||||
> {
|
||||
private:
|
||||
_T p_range;
|
||||
RangeSize<_T> p_chunksize;
|
||||
T p_range;
|
||||
RangeSize<T> p_chunksize;
|
||||
public:
|
||||
ChunksRange(): p_range(), p_chunksize(0) {}
|
||||
ChunksRange(const _T &range, RangeSize<_T> chs): p_range(range),
|
||||
ChunksRange(const T &range, RangeSize<T> chs): p_range(range),
|
||||
p_chunksize(chs) {}
|
||||
ChunksRange(const ChunksRange &it): p_range(it.p_range),
|
||||
p_chunksize(it.p_chunksize) {}
|
||||
|
@ -825,19 +825,19 @@ public:
|
|||
|
||||
bool pop_front() { return p_range.pop_front_n(p_chunksize) > 0; }
|
||||
bool push_front() {
|
||||
_T tmp = p_range;
|
||||
RangeSize<_T> an = tmp.push_front_n(p_chunksize);
|
||||
T tmp = p_range;
|
||||
RangeSize<T> an = tmp.push_front_n(p_chunksize);
|
||||
if (an != p_chunksize) return false;
|
||||
p_range = tmp;
|
||||
return true;
|
||||
}
|
||||
RangeSize<_T> pop_front_n(RangeSize<_T> n) {
|
||||
RangeSize<T> pop_front_n(RangeSize<T> n) {
|
||||
return p_range.pop_front_n(p_chunksize * n) / p_chunksize;
|
||||
}
|
||||
RangeSize<_T> push_front_n(RangeSize<_T> n) {
|
||||
_T tmp = p_range;
|
||||
RangeSize<_T> an = tmp.push_front_n(p_chunksize * n);
|
||||
RangeSize<_T> pn = an / p_chunksize;
|
||||
RangeSize<T> push_front_n(RangeSize<T> n) {
|
||||
T tmp = p_range;
|
||||
RangeSize<T> an = tmp.push_front_n(p_chunksize * n);
|
||||
RangeSize<T> pn = an / p_chunksize;
|
||||
if (!pn) return 0;
|
||||
if (pn == n) {
|
||||
p_range = tmp;
|
||||
|
@ -846,49 +846,49 @@ public:
|
|||
return p_range.push_front_n(p_chunksize * an) / p_chunksize;
|
||||
}
|
||||
|
||||
TakeRange<_T> front() const { return take(p_range, p_chunksize); }
|
||||
TakeRange<T> front() const { return take(p_range, p_chunksize); }
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
ChunksRange<_T> chunks(const _T &it, RangeSize<_T> chs) {
|
||||
return ChunksRange<_T>(it, chs);
|
||||
template<typename T>
|
||||
ChunksRange<T> chunks(const T &it, RangeSize<T> chs) {
|
||||
return ChunksRange<T>(it, chs);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
auto each(_T &r) -> decltype(r.each()) {
|
||||
template<typename T>
|
||||
auto each(T &r) -> decltype(r.each()) {
|
||||
return r.each();
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
auto each(const _T &r) -> decltype(r.each()) {
|
||||
template<typename T>
|
||||
auto each(const T &r) -> decltype(r.each()) {
|
||||
return r.each();
|
||||
}
|
||||
|
||||
template<typename _T, size_t _N>
|
||||
PointerRange<_T> each(_T (&array)[_N]) {
|
||||
return PointerRange<_T>(array, _N);
|
||||
template<typename T, size_t N>
|
||||
PointerRange<T> each(T (&array)[N]) {
|
||||
return PointerRange<T>(array, N);
|
||||
}
|
||||
|
||||
// range of
|
||||
template<typename _T> using RangeOf = decltype(octa::each(octa::declval<_T>()));
|
||||
template<typename T> using RangeOf = decltype(octa::each(octa::declval<T>()));
|
||||
|
||||
template<typename _T>
|
||||
struct HalfRange: InputRange<HalfRange<_T>,
|
||||
RangeCategory<_T>, RangeValue<_T>, RangeReference<_T>, RangeSize<_T>,
|
||||
RangeDifference<_T>
|
||||
template<typename T>
|
||||
struct HalfRange: InputRange<HalfRange<T>,
|
||||
RangeCategory<T>, RangeValue<T>, RangeReference<T>, RangeSize<T>,
|
||||
RangeDifference<T>
|
||||
> {
|
||||
private:
|
||||
_T p_beg;
|
||||
_T p_end;
|
||||
T p_beg;
|
||||
T p_end;
|
||||
public:
|
||||
HalfRange(): p_beg(), p_end() {}
|
||||
HalfRange(const HalfRange &range): p_beg(range.p_beg),
|
||||
p_end(range.p_end) {}
|
||||
HalfRange(HalfRange &&range): p_beg(octa::move(range.p_beg)),
|
||||
p_end(octa::move(range.p_end)) {}
|
||||
HalfRange(const _T &beg, const _T &end): p_beg(beg),
|
||||
HalfRange(const T &beg, const T &end): p_beg(beg),
|
||||
p_end(end) {}
|
||||
HalfRange(_T &&beg, _T &&end): p_beg(octa::move(beg)),
|
||||
HalfRange(T &&beg, T &&end): p_beg(octa::move(beg)),
|
||||
p_end(octa::move(end)) {}
|
||||
|
||||
HalfRange &operator=(const HalfRange &range) {
|
||||
|
@ -920,8 +920,8 @@ public:
|
|||
return p_end.next();
|
||||
}
|
||||
|
||||
RangeReference<_T> front() const { return *p_beg; }
|
||||
RangeReference<_T> back() const { return *(p_end - 1); }
|
||||
RangeReference<T> front() const { return *p_beg; }
|
||||
RangeReference<T> back() const { return *(p_end - 1); }
|
||||
|
||||
bool equals_front(const HalfRange &range) const {
|
||||
return p_beg == range.p_beg;
|
||||
|
@ -930,35 +930,35 @@ public:
|
|||
return p_end == range.p_end;
|
||||
}
|
||||
|
||||
RangeDifference<_T> distance_front(const HalfRange &range) const {
|
||||
RangeDifference<T> distance_front(const HalfRange &range) const {
|
||||
return range.p_beg - p_beg;
|
||||
}
|
||||
RangeDifference<_T> distance_back(const HalfRange &range) const {
|
||||
RangeDifference<T> distance_back(const HalfRange &range) const {
|
||||
return range.p_end - p_end;
|
||||
}
|
||||
|
||||
RangeSize<_T> size() const { return p_end - p_beg; }
|
||||
RangeSize<T> size() const { return p_end - p_beg; }
|
||||
|
||||
HalfRange<_T> slice(RangeSize<_T> start, RangeSize<_T> p_end) const {
|
||||
return HalfRange<_T>(p_beg + start, p_beg + p_end);
|
||||
HalfRange<T> slice(RangeSize<T> start, RangeSize<T> p_end) const {
|
||||
return HalfRange<T>(p_beg + start, p_beg + p_end);
|
||||
}
|
||||
|
||||
RangeReference<_T> operator[](RangeSize<_T> idx) const {
|
||||
RangeReference<T> operator[](RangeSize<T> idx) const {
|
||||
return p_beg[idx];
|
||||
}
|
||||
|
||||
void put(const RangeValue<_T> &v) {
|
||||
void put(const RangeValue<T> &v) {
|
||||
p_beg.range().put(v);
|
||||
}
|
||||
void put(RangeValue<_T> &&v) {
|
||||
void put(RangeValue<T> &&v) {
|
||||
p_beg.range().put(octa::move(v));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
HalfRange<RangeHalf<_T>>
|
||||
make_half_range(const RangeHalf<_T> &a, const RangeHalf<_T> &b) {
|
||||
return HalfRange<RangeHalf<_T>>(a, b);
|
||||
template<typename T>
|
||||
HalfRange<RangeHalf<T>>
|
||||
make_half_range(const RangeHalf<T> &a, const RangeHalf<T> &b) {
|
||||
return HalfRange<RangeHalf<T>>(a, b);
|
||||
}
|
||||
|
||||
} /* namespace octa */
|
||||
|
|
176
octa/string.h
176
octa/string.h
|
@ -16,9 +16,9 @@
|
|||
namespace octa {
|
||||
static constexpr size_t npos = -1;
|
||||
|
||||
template<typename _T, typename _A = octa::Allocator<_T>>
|
||||
template<typename T, typename A = octa::Allocator<T>>
|
||||
class StringBase {
|
||||
octa::Vector<_T> p_buf;
|
||||
octa::Vector<T> p_buf;
|
||||
|
||||
void terminate() {
|
||||
if (p_buf.empty() || (p_buf.back() != '\0')) p_buf.push('\0');
|
||||
|
@ -27,56 +27,56 @@ class StringBase {
|
|||
public:
|
||||
typedef size_t Size;
|
||||
typedef ptrdiff_t Difference;
|
||||
typedef _T Value;
|
||||
typedef _T &Reference;
|
||||
typedef const _T &ConstReference;
|
||||
typedef _T *Pointer;
|
||||
typedef const _T *ConstPointer;
|
||||
typedef PointerRange< _T> Range;
|
||||
typedef PointerRange<const _T> ConstRange;
|
||||
typedef _A Allocator;
|
||||
typedef T Value;
|
||||
typedef T &Reference;
|
||||
typedef const T &ConstReference;
|
||||
typedef T *Pointer;
|
||||
typedef const T *ConstPointer;
|
||||
typedef PointerRange< T> Range;
|
||||
typedef PointerRange<const T> ConstRange;
|
||||
typedef A Allocator;
|
||||
|
||||
StringBase(const _A &a = _A()): p_buf(1, '\0', a) {}
|
||||
StringBase(const A &a = A()): p_buf(1, '\0', a) {}
|
||||
|
||||
StringBase(const StringBase &s): p_buf(s.p_buf) {}
|
||||
StringBase(const StringBase &s, const _A &a):
|
||||
StringBase(const StringBase &s, const A &a):
|
||||
p_buf(s.p_buf, a) {}
|
||||
StringBase(StringBase &&s): p_buf(octa::move(s.p_buf)) {}
|
||||
StringBase(StringBase &&s, const _A &a):
|
||||
StringBase(StringBase &&s, const A &a):
|
||||
p_buf(octa::move(s.p_buf), a) {}
|
||||
|
||||
StringBase(const StringBase &s, size_t pos, size_t len = npos,
|
||||
const _A &a = _A()):
|
||||
const A &a = A()):
|
||||
p_buf(s.p_buf.each().slice(pos,
|
||||
(len == npos) ? s.p_buf.size() : (pos + len)), a) {
|
||||
terminate();
|
||||
}
|
||||
|
||||
/* TODO: traits for utf-16/utf-32 string lengths, for now assume char */
|
||||
StringBase(const _T *v, const _A &a = _A()):
|
||||
StringBase(const T *v, const A &a = A()):
|
||||
p_buf(ConstRange(v, strlen(v) + 1), a) {}
|
||||
|
||||
template<typename _R> StringBase(_R range, const _A &a = _A()):
|
||||
template<typename R> StringBase(R range, const A &a = A()):
|
||||
p_buf(range, a) {
|
||||
terminate();
|
||||
}
|
||||
|
||||
void clear() { p_buf.clear(); }
|
||||
|
||||
StringBase<_T> &operator=(const StringBase &v) {
|
||||
StringBase<T> &operator=(const StringBase &v) {
|
||||
p_buf.operator=(v);
|
||||
return *this;
|
||||
}
|
||||
StringBase<_T> &operator=(StringBase &&v) {
|
||||
StringBase<T> &operator=(StringBase &&v) {
|
||||
p_buf.operator=(octa::move(v));
|
||||
return *this;
|
||||
}
|
||||
StringBase<_T> &operator=(const _T *v) {
|
||||
StringBase<T> &operator=(const T *v) {
|
||||
p_buf = ConstRange(v, strlen(v) + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void resize(size_t n, _T v = _T()) {
|
||||
void resize(size_t n, T v = T()) {
|
||||
p_buf.pop();
|
||||
p_buf.resize(n, v);
|
||||
terminate();
|
||||
|
@ -86,20 +86,20 @@ public:
|
|||
p_buf.reserve(n + 1);
|
||||
}
|
||||
|
||||
_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) { return p_buf[i]; }
|
||||
const T &operator[](size_t i) const { 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) { return p_buf[i]; }
|
||||
const T &at(size_t i) const { return p_buf[i]; }
|
||||
|
||||
_T &front() { return p_buf[0]; }
|
||||
const _T &front() const { return p_buf[0]; };
|
||||
T &front() { return p_buf[0]; }
|
||||
const T &front() const { return p_buf[0]; };
|
||||
|
||||
_T &back() { return p_buf[size() - 1]; }
|
||||
const _T &back() const { return p_buf[size() - 1]; }
|
||||
T &back() { return p_buf[size() - 1]; }
|
||||
const T &back() const { return p_buf[size() - 1]; }
|
||||
|
||||
_T *data() { return p_buf.data(); }
|
||||
const _T *data() const { return p_buf.data(); }
|
||||
T *data() { return p_buf.data(); }
|
||||
const T *data() const { return p_buf.data(); }
|
||||
|
||||
size_t size() const {
|
||||
return p_buf.size() - 1;
|
||||
|
@ -111,54 +111,54 @@ public:
|
|||
|
||||
bool empty() const { return (size() == 0); }
|
||||
|
||||
void push(_T v) {
|
||||
void push(T v) {
|
||||
p_buf.back() = v;
|
||||
p_buf.push('\0');
|
||||
}
|
||||
|
||||
StringBase<_T> &append(const StringBase &s) {
|
||||
StringBase<T> &append(const StringBase &s) {
|
||||
p_buf.pop();
|
||||
p_buf.insert_range(p_buf.size(), s.p_buf.each());
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBase<_T> &append(const StringBase &s, size_t idx, size_t len) {
|
||||
StringBase<T> &append(const StringBase &s, size_t idx, size_t len) {
|
||||
p_buf.pop();
|
||||
p_buf.insert_range(p_buf.size(), octa::PointerRange<_T>(&s[idx],
|
||||
p_buf.insert_range(p_buf.size(), octa::PointerRange<T>(&s[idx],
|
||||
(len == npos) ? (s.size() - idx) : len));
|
||||
terminate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBase<_T> &append(const _T *s) {
|
||||
StringBase<T> &append(const T *s) {
|
||||
p_buf.pop();
|
||||
p_buf.insert_range(p_buf.size(), ConstRange(s,
|
||||
strlen(s) + 1));
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBase<_T> &append(size_t n, _T c) {
|
||||
StringBase<T> &append(size_t n, T c) {
|
||||
p_buf.pop();
|
||||
for (size_t i = 0; i < n; ++i) p_buf.push(c);
|
||||
p_buf.push('\0');
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename _R>
|
||||
StringBase<_T> &append_range(_R range) {
|
||||
template<typename R>
|
||||
StringBase<T> &append_range(R range) {
|
||||
p_buf.pop();
|
||||
p_buf.insert_range(p_buf.size(), range);
|
||||
terminate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBase<_T> &operator+=(const StringBase &s) {
|
||||
StringBase<T> &operator+=(const StringBase &s) {
|
||||
return append(s);
|
||||
}
|
||||
StringBase<_T> &operator+=(const _T *s) {
|
||||
StringBase<T> &operator+=(const T *s) {
|
||||
return append(s);
|
||||
}
|
||||
StringBase<_T> &operator+=(_T c) {
|
||||
StringBase<T> &operator+=(T c) {
|
||||
p_buf.pop();
|
||||
p_buf.push(c);
|
||||
p_buf.push('\0');
|
||||
|
@ -179,8 +179,8 @@ public:
|
|||
|
||||
typedef StringBase<char> String;
|
||||
|
||||
template<typename _T, typename _F>
|
||||
String concat(const _T v, const String &sep, _F func) {
|
||||
template<typename T, typename F>
|
||||
String concat(const T v, const String &sep, F func) {
|
||||
String ret;
|
||||
auto range = octa::each(v);
|
||||
if (range.empty()) return octa::move(ret);
|
||||
|
@ -193,8 +193,8 @@ String concat(const _T v, const String &sep, _F func) {
|
|||
return octa::move(ret);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
String concat(const _T &v, const String &sep = " ") {
|
||||
template<typename T>
|
||||
String concat(const T &v, const String &sep = " ") {
|
||||
String ret;
|
||||
auto range = octa::each(v);
|
||||
if (range.empty()) return octa::move(ret);
|
||||
|
@ -207,41 +207,41 @@ String concat(const _T &v, const String &sep = " ") {
|
|||
return octa::move(ret);
|
||||
}
|
||||
|
||||
template<typename _T, typename _F>
|
||||
String concat(std::initializer_list<_T> v, const String &sep, _F func) {
|
||||
template<typename T, typename F>
|
||||
String concat(std::initializer_list<T> v, const String &sep, F func) {
|
||||
return concat(octa::each(v), sep, func);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
String concat(std::initializer_list<_T> v, const String &sep = " ") {
|
||||
template<typename T>
|
||||
String concat(std::initializer_list<T> v, const String &sep = " ") {
|
||||
return concat(octa::each(v), sep);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
struct ToStringTest {
|
||||
template<typename _U, String (_U::*)() const> struct Test {};
|
||||
template<typename _U> static char test(Test<_U, &_U::to_string> *);
|
||||
template<typename _U> static int test(...);
|
||||
static constexpr bool value = (sizeof(test<_T>(0)) == sizeof(char));
|
||||
template<typename U, String (U::*)() const> struct Test {};
|
||||
template<typename U> static char test(Test<U, &U::to_string> *);
|
||||
template<typename U> static int test(...);
|
||||
static constexpr bool value = (sizeof(test<T>(0)) == sizeof(char));
|
||||
};
|
||||
}
|
||||
|
||||
template<typename _T> struct ToString {
|
||||
typedef _T Argument;
|
||||
template<typename T> struct ToString {
|
||||
typedef T Argument;
|
||||
typedef String Result;
|
||||
|
||||
template<typename _U>
|
||||
static String to_str(const _U &v,
|
||||
octa::EnableIf<octa::detail::ToStringTest<_U>::value, bool> = true
|
||||
template<typename U>
|
||||
static String to_str(const U &v,
|
||||
octa::EnableIf<octa::detail::ToStringTest<U>::value, bool> = true
|
||||
) {
|
||||
return v.to_string();
|
||||
}
|
||||
|
||||
template<typename _U>
|
||||
static String to_str(const _U &v,
|
||||
octa::EnableIf<!octa::detail::ToStringTest<_U>::value &&
|
||||
!octa::IsScalar<_U>::value, bool> = true
|
||||
template<typename U>
|
||||
static String to_str(const U &v,
|
||||
octa::EnableIf<!octa::detail::ToStringTest<U>::value &&
|
||||
!octa::IsScalar<U>::value, bool> = true
|
||||
) {
|
||||
String ret("{");
|
||||
ret += concat(octa::each(v), ", ", ToString<octa::RangeReference<
|
||||
|
@ -251,24 +251,24 @@ template<typename _T> struct ToString {
|
|||
return octa::move(ret);
|
||||
}
|
||||
|
||||
template<typename _U>
|
||||
static String to_str(const _U &v,
|
||||
octa::EnableIf<!octa::detail::ToStringTest<_U>::value &&
|
||||
octa::IsScalar<_U>::value, bool> = true
|
||||
template<typename U>
|
||||
static String to_str(const U &v,
|
||||
octa::EnableIf<!octa::detail::ToStringTest<U>::value &&
|
||||
octa::IsScalar<U>::value, bool> = true
|
||||
) {
|
||||
return ToString<_U>()(v);
|
||||
return ToString<U>()(v);
|
||||
}
|
||||
|
||||
String operator()(const _T &v) {
|
||||
String operator()(const T &v) {
|
||||
return octa::move(to_str<octa::RemoveCv<
|
||||
octa::RemoveReference<_T>
|
||||
octa::RemoveReference<T>
|
||||
>>(v));
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename _T>
|
||||
void str_printf(octa::Vector<char> *s, const char *fmt, _T v) {
|
||||
template<typename T>
|
||||
void str_printf(octa::Vector<char> *s, const char *fmt, T v) {
|
||||
char buf[256];
|
||||
int n = snprintf(buf, sizeof(buf), fmt, v);
|
||||
s->clear();
|
||||
|
@ -303,11 +303,11 @@ template<> struct ToString<char> {
|
|||
}
|
||||
};
|
||||
|
||||
#define OCTA_TOSTR_NUM(_T, fmt) \
|
||||
template<> struct ToString<_T> { \
|
||||
typedef _T Argument; \
|
||||
#define OCTA_TOSTR_NUM(T, fmt) \
|
||||
template<> struct ToString<T> { \
|
||||
typedef T Argument; \
|
||||
typedef String Result; \
|
||||
String operator()(_T v) { \
|
||||
String operator()(T v) { \
|
||||
String ret; \
|
||||
octa::detail::str_printf((octa::Vector<char> *)&ret, fmt, v); \
|
||||
return octa::move(ret); \
|
||||
|
@ -327,8 +327,8 @@ OCTA_TOSTR_NUM(ldouble, "%Lf")
|
|||
|
||||
#undef OCTA_TOSTR_NUM
|
||||
|
||||
template<typename _T> struct ToString<_T *> {
|
||||
typedef _T *Argument;
|
||||
template<typename T> struct ToString<T *> {
|
||||
typedef T *Argument;
|
||||
typedef String Result;
|
||||
String operator()(Argument v) {
|
||||
String ret;
|
||||
|
@ -345,30 +345,30 @@ template<> struct ToString<String> {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename _T, typename _U> struct ToString<octa::Pair<_T, _U>> {
|
||||
typedef const octa::Pair<_T, _U> &Argument;
|
||||
template<typename T, typename U> struct ToString<octa::Pair<T, U>> {
|
||||
typedef const octa::Pair<T, U> &Argument;
|
||||
typedef String Result;
|
||||
String operator()(Argument v) {
|
||||
String ret("{");
|
||||
ret += ToString<octa::RemoveCv<octa::RemoveReference<_T>>>()
|
||||
ret += ToString<octa::RemoveCv<octa::RemoveReference<T>>>()
|
||||
(v.first);
|
||||
ret += ", ";
|
||||
ret += ToString<octa::RemoveCv<octa::RemoveReference<_U>>>()
|
||||
ret += ToString<octa::RemoveCv<octa::RemoveReference<U>>>()
|
||||
(v.second);
|
||||
ret += "}";
|
||||
return octa::move(ret);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
String to_string(const _T &v) {
|
||||
return octa::move(ToString<octa::RemoveCv<octa::RemoveReference<_T>>>
|
||||
template<typename T>
|
||||
String to_string(const T &v) {
|
||||
return octa::move(ToString<octa::RemoveCv<octa::RemoveReference<T>>>
|
||||
()(v));
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
String to_string(std::initializer_list<_T> init) {
|
||||
return octa::move(ToString<std::initializer_list<_T>>()(init));
|
||||
template<typename T>
|
||||
String to_string(std::initializer_list<T> init) {
|
||||
return octa::move(ToString<std::initializer_list<T>>()(init));
|
||||
}
|
||||
|
||||
} /* namespace octa */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
118
octa/utility.h
118
octa/utility.h
|
@ -14,78 +14,78 @@ namespace octa {
|
|||
|
||||
/* move */
|
||||
|
||||
template<typename _T>
|
||||
static inline constexpr RemoveReference<_T> &&move(_T &&v) {
|
||||
return static_cast<RemoveReference<_T> &&>(v);
|
||||
template<typename T>
|
||||
static inline constexpr RemoveReference<T> &&move(T &&v) {
|
||||
return static_cast<RemoveReference<T> &&>(v);
|
||||
}
|
||||
|
||||
/* forward */
|
||||
|
||||
template<typename _T>
|
||||
static inline constexpr _T &&forward(RemoveReference<_T> &v) {
|
||||
return static_cast<_T &&>(v);
|
||||
template<typename T>
|
||||
static inline constexpr T &&forward(RemoveReference<T> &v) {
|
||||
return static_cast<T &&>(v);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
static inline constexpr _T &&forward(RemoveReference<_T> &&v) {
|
||||
return static_cast<_T &&>(v);
|
||||
template<typename T>
|
||||
static inline constexpr T &&forward(RemoveReference<T> &&v) {
|
||||
return static_cast<T &&>(v);
|
||||
}
|
||||
|
||||
/* exchange */
|
||||
|
||||
template<typename _T, typename _U = _T>
|
||||
_T exchange(_T &v, _U &&nv) {
|
||||
_T old = move(v);
|
||||
v = forward<_U>(nv);
|
||||
template<typename T, typename U = T>
|
||||
T exchange(T &v, U &&nv) {
|
||||
T old = move(v);
|
||||
v = forward<U>(nv);
|
||||
return old;
|
||||
}
|
||||
|
||||
/* declval */
|
||||
|
||||
template<typename _T> AddRvalueReference<_T> declval();
|
||||
template<typename T> AddRvalueReference<T> declval();
|
||||
|
||||
/* swap */
|
||||
|
||||
namespace detail {
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
struct SwapTest {
|
||||
template<typename _U, void (_U::*)(_U &)> struct Test {};
|
||||
template<typename _U> static char test(Test<_U, &_U::swap> *);
|
||||
template<typename _U> static int test(...);
|
||||
static constexpr bool value = (sizeof(test<_T>(0)) == sizeof(char));
|
||||
template<typename U, void (U::*)(U &)> struct Test {};
|
||||
template<typename U> static char test(Test<U, &U::swap> *);
|
||||
template<typename U> static int test(...);
|
||||
static constexpr bool value = (sizeof(test<T>(0)) == sizeof(char));
|
||||
};
|
||||
|
||||
template<typename _T> inline void swap(_T &a, _T &b, EnableIf<
|
||||
octa::detail::SwapTest<_T>::value, bool
|
||||
template<typename T> inline void swap(T &a, T &b, EnableIf<
|
||||
octa::detail::SwapTest<T>::value, bool
|
||||
> = true) {
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template<typename _T> inline void swap(_T &a, _T &b, EnableIf<
|
||||
!octa::detail::SwapTest<_T>::value, bool
|
||||
template<typename T> inline void swap(T &a, T &b, EnableIf<
|
||||
!octa::detail::SwapTest<T>::value, bool
|
||||
> = true) {
|
||||
_T c(octa::move(a));
|
||||
T c(octa::move(a));
|
||||
a = octa::move(b);
|
||||
b = octa::move(c);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _T> void swap(_T &a, _T &b) {
|
||||
template<typename T> void swap(T &a, T &b) {
|
||||
octa::detail::swap(a, b);
|
||||
}
|
||||
|
||||
template<typename _T, size_t _N> void swap(_T (&a)[_N], _T (&b)[_N]) {
|
||||
for (size_t i = 0; i < _N; ++i) {
|
||||
template<typename T, size_t N> void swap(T (&a)[N], T (&b)[N]) {
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
octa::swap(a[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* pair */
|
||||
|
||||
template<typename _T, typename _U>
|
||||
template<typename T, typename U>
|
||||
struct Pair {
|
||||
_T first;
|
||||
_U second;
|
||||
T first;
|
||||
U second;
|
||||
|
||||
Pair() = default;
|
||||
~Pair() = default;
|
||||
|
@ -93,17 +93,17 @@ struct Pair {
|
|||
Pair(const Pair &) = default;
|
||||
Pair(Pair &&) = default;
|
||||
|
||||
Pair(const _T &x, const _U &y): first(x), second(y) {}
|
||||
Pair(const T &x, const U &y): first(x), second(y) {}
|
||||
|
||||
template<typename _TT, typename _UU>
|
||||
Pair(_TT &&x, _UU &&y):
|
||||
first(octa::forward<_TT>(x)), second(octa::forward<_UU>(y)) {}
|
||||
template<typename TT, typename UU>
|
||||
Pair(TT &&x, UU &&y):
|
||||
first(octa::forward<TT>(x)), second(octa::forward<UU>(y)) {}
|
||||
|
||||
template<typename _TT, typename _UU>
|
||||
Pair(const Pair<_TT, _UU> &v): first(v.first), second(v.second) {}
|
||||
template<typename TT, typename UU>
|
||||
Pair(const Pair<TT, UU> &v): first(v.first), second(v.second) {}
|
||||
|
||||
template<typename _TT, typename _UU>
|
||||
Pair(Pair<_TT, _UU> &&v):
|
||||
template<typename TT, typename UU>
|
||||
Pair(Pair<TT, UU> &&v):
|
||||
first(octa::move(v.first)), second(octa::move(v.second)) {}
|
||||
|
||||
Pair &operator=(const Pair &v) {
|
||||
|
@ -112,8 +112,8 @@ struct Pair {
|
|||
return *this;
|
||||
}
|
||||
|
||||
template<typename _TT, typename _UU>
|
||||
Pair &operator=(const Pair<_TT, _UU> &v) {
|
||||
template<typename TT, typename UU>
|
||||
Pair &operator=(const Pair<TT, UU> &v) {
|
||||
first = v.first;
|
||||
second = v.second;
|
||||
return *this;
|
||||
|
@ -125,10 +125,10 @@ struct Pair {
|
|||
return *this;
|
||||
}
|
||||
|
||||
template<typename _TT, typename _UU>
|
||||
Pair &operator=(Pair<_TT, _UU> &&v) {
|
||||
first = octa::forward<_TT>(v.first);
|
||||
second = octa::forward<_UU>(v.second);
|
||||
template<typename TT, typename UU>
|
||||
Pair &operator=(Pair<TT, UU> &&v) {
|
||||
first = octa::forward<TT>(v.first);
|
||||
second = octa::forward<UU>(v.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -138,32 +138,32 @@ struct Pair {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename _T> struct ReferenceWrapper;
|
||||
template<typename T> struct ReferenceWrapper;
|
||||
|
||||
namespace detail {
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
struct MakePairRetBase {
|
||||
typedef _T Type;
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
struct MakePairRetBase<ReferenceWrapper<_T>> {
|
||||
typedef _T &Type;
|
||||
template<typename T>
|
||||
struct MakePairRetBase<ReferenceWrapper<T>> {
|
||||
typedef T &Type;
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
template<typename T>
|
||||
struct MakePairRet {
|
||||
typedef typename octa::detail::MakePairRetBase<octa::Decay<_T>>::Type Type;
|
||||
typedef typename octa::detail::MakePairRetBase<octa::Decay<T>>::Type Type;
|
||||
};
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename _T, typename _U>
|
||||
Pair<typename octa::detail::MakePairRet<_T>::Type,
|
||||
typename octa::detail::MakePairRet<_U>::Type
|
||||
> make_pair(_T &&a, _U &&b) {
|
||||
return Pair<typename octa::detail::MakePairRet<_T>::Type,
|
||||
typename octa::detail::MakePairRet<_U>::Type
|
||||
>(forward<_T>(a), forward<_U>(b));;
|
||||
template<typename T, typename U>
|
||||
Pair<typename octa::detail::MakePairRet<T>::Type,
|
||||
typename octa::detail::MakePairRet<U>::Type
|
||||
> make_pair(T &&a, U &&b) {
|
||||
return Pair<typename octa::detail::MakePairRet<T>::Type,
|
||||
typename octa::detail::MakePairRet<U>::Type
|
||||
>(forward<T>(a), forward<U>(b));;
|
||||
}
|
||||
|
||||
} /* namespace octa */
|
||||
|
|
190
octa/vector.h
190
octa/vector.h
|
@ -19,20 +19,20 @@
|
|||
namespace octa {
|
||||
|
||||
namespace detail {
|
||||
template<typename _T, typename _A, bool = octa::IsEmpty<_A>::value>
|
||||
template<typename T, typename A, bool = octa::IsEmpty<A>::value>
|
||||
struct VectorPair;
|
||||
|
||||
template<typename _T, typename _A>
|
||||
struct VectorPair<_T, _A, false> { /* non-empty allocator */
|
||||
_T *p_ptr;
|
||||
_A p_a;
|
||||
template<typename T, typename A>
|
||||
struct VectorPair<T, A, false> { /* non-empty allocator */
|
||||
T *p_ptr;
|
||||
A p_a;
|
||||
|
||||
template<typename _U>
|
||||
VectorPair(_T *ptr, _U &&a): p_ptr(ptr),
|
||||
p_a(octa::forward<_U>(a)) {}
|
||||
template<typename U>
|
||||
VectorPair(T *ptr, U &&a): p_ptr(ptr),
|
||||
p_a(octa::forward<U>(a)) {}
|
||||
|
||||
_A &get_alloc() { return p_a; }
|
||||
const _A &get_alloc() const { return p_a; }
|
||||
A &get_alloc() { return p_a; }
|
||||
const A &get_alloc() const { return p_a; }
|
||||
|
||||
void swap(VectorPair &v) {
|
||||
octa::swap(p_ptr, v.p_ptr);
|
||||
|
@ -40,16 +40,16 @@ namespace detail {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename _T, typename _A>
|
||||
struct VectorPair<_T, _A, true>: _A { /* empty allocator */
|
||||
_T *p_ptr;
|
||||
template<typename T, typename A>
|
||||
struct VectorPair<T, A, true>: A { /* empty allocator */
|
||||
T *p_ptr;
|
||||
|
||||
template<typename _U>
|
||||
VectorPair(_T *ptr, _U &&a):
|
||||
_A(octa::forward<_U>(a)), p_ptr(ptr) {}
|
||||
template<typename U>
|
||||
VectorPair(T *ptr, U &&a):
|
||||
A(octa::forward<U>(a)), p_ptr(ptr) {}
|
||||
|
||||
_A &get_alloc() { return *this; }
|
||||
const _A &get_alloc() const { return *this; }
|
||||
A &get_alloc() { return *this; }
|
||||
const A &get_alloc() const { return *this; }
|
||||
|
||||
void swap(VectorPair &v) {
|
||||
octa::swap(p_ptr, v.p_ptr);
|
||||
|
@ -57,9 +57,9 @@ namespace detail {
|
|||
};
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename _T, typename _A = octa::Allocator<_T>>
|
||||
template<typename T, typename A = octa::Allocator<T>>
|
||||
class Vector {
|
||||
typedef octa::detail::VectorPair<_T, _A> _vp_type;
|
||||
typedef octa::detail::VectorPair<T, A> _vp_type;
|
||||
|
||||
_vp_type p_buf;
|
||||
size_t p_len, p_cap;
|
||||
|
@ -72,11 +72,11 @@ class Vector {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename _R>
|
||||
void ctor_from_range(_R &range, octa::EnableIf<
|
||||
octa::IsFiniteRandomAccessRange<_R>::value, bool
|
||||
template<typename R>
|
||||
void ctor_from_range(R &range, octa::EnableIf<
|
||||
octa::IsFiniteRandomAccessRange<R>::value, bool
|
||||
> = true) {
|
||||
octa::RangeSize<_R> l = range.size();
|
||||
octa::RangeSize<R> l = range.size();
|
||||
reserve(l);
|
||||
p_len = l;
|
||||
for (size_t i = 0; !range.empty(); range.pop_front()) {
|
||||
|
@ -86,9 +86,9 @@ class Vector {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename _R>
|
||||
void ctor_from_range(_R &range, EnableIf<
|
||||
!octa::IsFiniteRandomAccessRange<_R>::value, bool
|
||||
template<typename R>
|
||||
void ctor_from_range(R &range, EnableIf<
|
||||
!octa::IsFiniteRandomAccessRange<R>::value, bool
|
||||
> = true) {
|
||||
size_t i = 0;
|
||||
for (; !range.empty(); range.pop_front()) {
|
||||
|
@ -101,11 +101,11 @@ class Vector {
|
|||
}
|
||||
|
||||
void copy_contents(const Vector &v) {
|
||||
if (octa::IsPod<_T>()) {
|
||||
memcpy(p_buf.p_ptr, v.p_buf.p_ptr, p_len * sizeof(_T));
|
||||
if (octa::IsPod<T>()) {
|
||||
memcpy(p_buf.p_ptr, v.p_buf.p_ptr, p_len * sizeof(T));
|
||||
} else {
|
||||
_T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + p_len;
|
||||
_T *vbuf = v.p_buf.p_ptr;
|
||||
T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + p_len;
|
||||
T *vbuf = v.p_buf.p_ptr;
|
||||
while (cur != last) {
|
||||
octa::allocator_construct(p_buf.get_alloc(),
|
||||
cur++, *vbuf++);
|
||||
|
@ -116,24 +116,24 @@ class Vector {
|
|||
public:
|
||||
enum { MIN_SIZE = 8 };
|
||||
|
||||
typedef size_t Size;
|
||||
typedef ptrdiff_t Difference;
|
||||
typedef _T Value;
|
||||
typedef _T &Reference;
|
||||
typedef const _T &ConstReference;
|
||||
typedef _T *Pointer;
|
||||
typedef const _T *ConstPointer;
|
||||
typedef PointerRange< _T> Range;
|
||||
typedef PointerRange<const _T> ConstRange;
|
||||
typedef _A Allocator;
|
||||
typedef size_t Size;
|
||||
typedef ptrdiff_t Difference;
|
||||
typedef T Value;
|
||||
typedef T &Reference;
|
||||
typedef const T &ConstReference;
|
||||
typedef T *Pointer;
|
||||
typedef const T *ConstPointer;
|
||||
typedef PointerRange< T> Range;
|
||||
typedef PointerRange<const T> ConstRange;
|
||||
typedef A Allocator;
|
||||
|
||||
Vector(const _A &a = _A()): p_buf(nullptr, a), p_len(0), p_cap(0) {}
|
||||
Vector(const A &a = A()): p_buf(nullptr, a), p_len(0), p_cap(0) {}
|
||||
|
||||
explicit Vector(size_t n, const _T &val = _T(),
|
||||
const _A &al = _A()): Vector(al) {
|
||||
explicit Vector(size_t n, const T &val = T(),
|
||||
const A &al = A()): Vector(al) {
|
||||
p_buf.p_ptr = octa::allocator_allocate(p_buf.get_alloc(), n);
|
||||
p_len = p_cap = n;
|
||||
_T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + n;
|
||||
T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + n;
|
||||
while (cur != last)
|
||||
octa::allocator_construct(p_buf.get_alloc(), cur++, val);
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ public:
|
|||
copy_contents(v);
|
||||
}
|
||||
|
||||
Vector(const Vector &v, const _A &a): p_buf(nullptr, a),
|
||||
Vector(const Vector &v, const A &a): p_buf(nullptr, a),
|
||||
p_len(0), p_cap(0) {
|
||||
reserve(v.p_cap);
|
||||
p_len = v.p_len;
|
||||
|
@ -159,16 +159,16 @@ public:
|
|||
v.p_len = v.p_cap = 0;
|
||||
}
|
||||
|
||||
Vector(Vector &&v, const _A &a) {
|
||||
Vector(Vector &&v, const A &a) {
|
||||
if (a != v.a) {
|
||||
p_buf.get_alloc() = a;
|
||||
reserve(v.p_cap);
|
||||
p_len = v.p_len;
|
||||
if (octa::IsPod<_T>()) {
|
||||
memcpy(p_buf.p_ptr, v.p_buf.p_ptr, p_len * sizeof(_T));
|
||||
if (octa::IsPod<T>()) {
|
||||
memcpy(p_buf.p_ptr, v.p_buf.p_ptr, p_len * sizeof(T));
|
||||
} else {
|
||||
_T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + p_len;
|
||||
_T *vbuf = v.p_buf.p_ptr;
|
||||
T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + p_len;
|
||||
T *vbuf = v.p_buf.p_ptr;
|
||||
while (cur != last) {
|
||||
octa::allocator_construct(p_buf.get_alloc(), cur++,
|
||||
octa::move(*vbuf++));
|
||||
|
@ -184,9 +184,9 @@ public:
|
|||
v.p_len = v.p_cap = 0;
|
||||
}
|
||||
|
||||
Vector(InitializerList<_T> v, const _A &a = _A()): Vector(a) {
|
||||
Vector(InitializerList<T> v, const A &a = A()): Vector(a) {
|
||||
size_t l = v.end() - v.begin();
|
||||
const _T *ptr = v.begin();
|
||||
const T *ptr = v.begin();
|
||||
reserve(l);
|
||||
for (size_t i = 0; i < l; ++i)
|
||||
octa::allocator_construct(p_buf.get_alloc(),
|
||||
|
@ -194,7 +194,7 @@ public:
|
|||
p_len = l;
|
||||
}
|
||||
|
||||
template<typename _R> Vector(_R range, const _A &a = _A()):
|
||||
template<typename R> Vector(R range, const A &a = A()):
|
||||
Vector(a) {
|
||||
ctor_from_range(range);
|
||||
}
|
||||
|
@ -205,8 +205,8 @@ public:
|
|||
}
|
||||
|
||||
void clear() {
|
||||
if (p_len > 0 && !octa::IsPod<_T>()) {
|
||||
_T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + p_len;
|
||||
if (p_len > 0 && !octa::IsPod<T>()) {
|
||||
T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + p_len;
|
||||
while (cur != last)
|
||||
octa::allocator_destroy(p_buf.get_alloc(), cur++);
|
||||
}
|
||||
|
@ -232,14 +232,14 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
Vector &operator=(InitializerList<_T> il) {
|
||||
Vector &operator=(InitializerList<T> il) {
|
||||
clear();
|
||||
size_t ilen = il.end() - il.begin();
|
||||
reserve(ilen);
|
||||
if (octa::IsPod<_T>()) {
|
||||
if (octa::IsPod<T>()) {
|
||||
memcpy(p_buf.p_ptr, il.begin(), ilen);
|
||||
} else {
|
||||
_T *tbuf = p_buf.p_ptr, *ibuf = il.begin(),
|
||||
T *tbuf = p_buf.p_ptr, *ibuf = il.begin(),
|
||||
*last = il.end();
|
||||
while (ibuf != last) {
|
||||
octa::allocator_construct(p_buf.get_alloc(),
|
||||
|
@ -250,23 +250,23 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
template<typename _R>
|
||||
Vector &operator=(_R range) {
|
||||
template<typename R>
|
||||
Vector &operator=(R range) {
|
||||
clear();
|
||||
ctor_from_range(range);
|
||||
}
|
||||
|
||||
void resize(size_t n, const _T &v = _T()) {
|
||||
void resize(size_t n, const T &v = T()) {
|
||||
size_t l = p_len;
|
||||
reserve(n);
|
||||
p_len = n;
|
||||
if (octa::IsPod<_T>()) {
|
||||
if (octa::IsPod<T>()) {
|
||||
for (size_t i = l; i < p_len; ++i) {
|
||||
p_buf.p_ptr[i] = _T(v);
|
||||
p_buf.p_ptr[i] = T(v);
|
||||
}
|
||||
} else {
|
||||
_T *first = p_buf.p_ptr + l;
|
||||
_T *last = p_buf.p_ptr + p_len;
|
||||
T *first = p_buf.p_ptr + l;
|
||||
T *last = p_buf.p_ptr + p_len;
|
||||
while (first != last)
|
||||
octa::allocator_construct(p_buf.get_alloc(), first++, v);
|
||||
}
|
||||
|
@ -280,12 +280,12 @@ public:
|
|||
} else {
|
||||
while (p_cap < n) p_cap *= 2;
|
||||
}
|
||||
_T *tmp = octa::allocator_allocate(p_buf.get_alloc(), p_cap);
|
||||
T *tmp = octa::allocator_allocate(p_buf.get_alloc(), p_cap);
|
||||
if (oc > 0) {
|
||||
if (octa::IsPod<_T>()) {
|
||||
memcpy(tmp, p_buf.p_ptr, p_len * sizeof(_T));
|
||||
if (octa::IsPod<T>()) {
|
||||
memcpy(tmp, p_buf.p_ptr, p_len * sizeof(T));
|
||||
} else {
|
||||
_T *cur = p_buf.p_ptr, *tcur = tmp,
|
||||
T *cur = p_buf.p_ptr, *tcur = tmp,
|
||||
*last = tmp + p_len;
|
||||
while (tcur != last) {
|
||||
octa::allocator_construct(p_buf.get_alloc(), tcur++,
|
||||
|
@ -299,35 +299,35 @@ public:
|
|||
p_buf.p_ptr = tmp;
|
||||
}
|
||||
|
||||
_T &operator[](size_t i) { return p_buf.p_ptr[i]; }
|
||||
const _T &operator[](size_t i) const { return p_buf.p_ptr[i]; }
|
||||
T &operator[](size_t i) { return p_buf.p_ptr[i]; }
|
||||
const T &operator[](size_t i) const { return p_buf.p_ptr[i]; }
|
||||
|
||||
_T &at(size_t i) { return p_buf.p_ptr[i]; }
|
||||
const _T &at(size_t i) const { return p_buf.p_ptr[i]; }
|
||||
T &at(size_t i) { return p_buf.p_ptr[i]; }
|
||||
const T &at(size_t i) const { return p_buf.p_ptr[i]; }
|
||||
|
||||
_T &push(const _T &v) {
|
||||
T &push(const T &v) {
|
||||
if (p_len == p_cap) reserve(p_len + 1);
|
||||
octa::allocator_construct(p_buf.get_alloc(),
|
||||
&p_buf.p_ptr[p_len], v);
|
||||
return p_buf.p_ptr[p_len++];
|
||||
}
|
||||
|
||||
_T &push() {
|
||||
T &push() {
|
||||
if (p_len == p_cap) reserve(p_len + 1);
|
||||
octa::allocator_construct(p_buf.get_alloc(), &p_buf.p_ptr[p_len]);
|
||||
return p_buf.p_ptr[p_len++];
|
||||
}
|
||||
|
||||
template<typename ..._U>
|
||||
_T &emplace_back(_U &&...args) {
|
||||
template<typename ...U>
|
||||
T &emplace_back(U &&...args) {
|
||||
if (p_len == p_cap) reserve(p_len + 1);
|
||||
octa::allocator_construct(p_buf.get_alloc(), &p_buf.p_ptr[p_len],
|
||||
octa::forward<_U>(args)...);
|
||||
octa::forward<U>(args)...);
|
||||
return p_buf.p_ptr[p_len++];
|
||||
}
|
||||
|
||||
void pop() {
|
||||
if (!octa::IsPod<_T>()) {
|
||||
if (!octa::IsPod<T>()) {
|
||||
octa::allocator_destroy(p_buf.get_alloc(),
|
||||
&p_buf.p_ptr[--p_len]);
|
||||
} else {
|
||||
|
@ -335,14 +335,14 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
_T &front() { return p_buf.p_ptr[0]; }
|
||||
const _T &front() const { return p_buf.p_ptr[0]; }
|
||||
T &front() { return p_buf.p_ptr[0]; }
|
||||
const T &front() const { return p_buf.p_ptr[0]; }
|
||||
|
||||
_T &back() { return p_buf.p_ptr[p_len - 1]; }
|
||||
const _T &back() const { return p_buf.p_ptr[p_len - 1]; }
|
||||
T &back() { return p_buf.p_ptr[p_len - 1]; }
|
||||
const T &back() const { return p_buf.p_ptr[p_len - 1]; }
|
||||
|
||||
_T *data() { return p_buf.p_ptr; }
|
||||
const _T *data() const { return p_buf.p_ptr; }
|
||||
T *data() { return p_buf.p_ptr; }
|
||||
const T *data() const { return p_buf.p_ptr; }
|
||||
|
||||
size_t size() const { return p_len; }
|
||||
size_t capacity() const { return p_cap; }
|
||||
|
@ -351,30 +351,30 @@ public:
|
|||
|
||||
bool in_range(size_t idx) { return idx < p_len; }
|
||||
bool in_range(int idx) { return idx >= 0 && size_t(idx) < p_len; }
|
||||
bool in_range(const _T *ptr) {
|
||||
bool in_range(const T *ptr) {
|
||||
return ptr >= p_buf.p_ptr && ptr < &p_buf.p_ptr[p_len];
|
||||
}
|
||||
|
||||
_T *disown() {
|
||||
_T *r = p_buf.p_ptr;
|
||||
T *disown() {
|
||||
T *r = p_buf.p_ptr;
|
||||
p_buf.p_ptr = nullptr;
|
||||
p_len = p_cap = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
_T *insert(size_t idx, _T &&v) {
|
||||
T *insert(size_t idx, T &&v) {
|
||||
insert_base(idx, 1);
|
||||
p_buf.p_ptr[idx] = octa::move(v);
|
||||
return &p_buf.p_ptr[idx];
|
||||
}
|
||||
|
||||
_T *insert(size_t idx, const _T &v) {
|
||||
T *insert(size_t idx, const T &v) {
|
||||
insert_base(idx, 1);
|
||||
p_buf.p_ptr[idx] = v;
|
||||
return &p_buf.p_ptr[idx];
|
||||
}
|
||||
|
||||
_T *insert(size_t idx, size_t n, const _T &v) {
|
||||
T *insert(size_t idx, size_t n, const T &v) {
|
||||
insert_base(idx, n);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
p_buf.p_ptr[idx + i] = v;
|
||||
|
@ -382,8 +382,8 @@ public:
|
|||
return &p_buf.p_ptr[idx];
|
||||
}
|
||||
|
||||
template<typename _U>
|
||||
_T *insert_range(size_t idx, _U range) {
|
||||
template<typename U>
|
||||
T *insert_range(size_t idx, U range) {
|
||||
size_t l = range.size();
|
||||
insert_base(idx, l);
|
||||
for (size_t i = 0; i < l; ++i) {
|
||||
|
@ -393,7 +393,7 @@ public:
|
|||
return &p_buf.p_ptr[idx];
|
||||
}
|
||||
|
||||
_T *insert(size_t idx, InitializerList<_T> il) {
|
||||
T *insert(size_t idx, InitializerList<T> il) {
|
||||
return insert_range(idx, octa::each(il));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue