forked from OctaForge/libostd
uglify the code by using unique identifiers only (prevent macro conflicts)
This commit is contained in:
parent
8bfd38f2e6
commit
bfc94e31d7
706
octa/algorithm.h
706
octa/algorithm.h
|
@ -17,545 +17,557 @@ namespace octa {
|
|||
|
||||
/* partitioning */
|
||||
|
||||
template<typename R, typename U>
|
||||
R partition(R range, U pred) {
|
||||
R ret = range;
|
||||
for (; !range.empty(); range.pop_front()) {
|
||||
if (pred(range.front())) {
|
||||
swap(range.front(), ret.front());
|
||||
ret.pop_front();
|
||||
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());
|
||||
__ret.pop_front();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return __ret;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* sorting */
|
||||
|
||||
template<typename R, typename C>
|
||||
void __octa_insort(R range, C compare) {
|
||||
RangeSize<R> rlen = range.size();
|
||||
for (RangeSize<R> i = 1; i < rlen; ++i) {
|
||||
RangeSize<R> j = i;
|
||||
RangeReference<R> v = range[i];
|
||||
while (j > 0 && !compare(range[j - 1], v)) {
|
||||
range[j] = range[j - 1];
|
||||
--j;
|
||||
template<typename _R, typename _C>
|
||||
void __octa_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;
|
||||
}
|
||||
range[j] = v;
|
||||
__range[__j] = __v;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
template<typename _T, typename _U>
|
||||
struct __OctaUnaryCompare {
|
||||
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 __octa_hs_sift_down(R range, RangeSize<R> s,
|
||||
RangeSize<R> e, C compare) {
|
||||
RangeSize<R> r = s;
|
||||
while ((r * 2 + 1) <= e) {
|
||||
RangeSize<R> ch = r * 2 + 1;
|
||||
RangeSize<R> sw = r;
|
||||
if (compare(range[sw], range[ch]))
|
||||
sw = ch;
|
||||
if (((ch + 1) <= e) && compare(range[sw], range[ch + 1]))
|
||||
sw = ch + 1;
|
||||
if (sw != r) {
|
||||
swap(range[r], range[sw]);
|
||||
r = sw;
|
||||
template<typename _R, typename _C>
|
||||
void __octa_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;
|
||||
if (__compare(__range[__sw], __range[__ch]))
|
||||
__sw = __ch;
|
||||
if (((__ch + 1) <= __e) && __compare(__range[__sw], __range[__ch + 1]))
|
||||
__sw = __ch + 1;
|
||||
if (__sw != __r) {
|
||||
octa::swap(__range[__r], __range[__sw]);
|
||||
__r = __sw;
|
||||
} else return;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R, typename C>
|
||||
void __octa_heapsort(R range, C compare) {
|
||||
RangeSize<R> len = range.size();
|
||||
RangeSize<R> st = (len - 2) / 2;
|
||||
template<typename _R, typename _C>
|
||||
void __octa_heapsort(_R __range, _C __compare) {
|
||||
octa::RangeSize<_R> __len = __range.size();
|
||||
octa::RangeSize<_R> __st = (__len - 2) / 2;
|
||||
for (;;) {
|
||||
__octa_hs_sift_down(range, st, len - 1, compare);
|
||||
if (st-- == 0) break;
|
||||
__octa_hs_sift_down(__range, __st, __len - 1, __compare);
|
||||
if (__st-- == 0) break;
|
||||
}
|
||||
RangeSize<R> e = len - 1;
|
||||
while (e > 0) {
|
||||
swap(range[e], range[0]);
|
||||
--e;
|
||||
__octa_hs_sift_down(range, 0, e, compare);
|
||||
octa::RangeSize<_R> __e = __len - 1;
|
||||
while (__e > 0) {
|
||||
octa::swap(__range[__e], __range[0]);
|
||||
--__e;
|
||||
__octa_hs_sift_down(__range, 0, __e, __compare);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R, typename C>
|
||||
void __octa_introloop(R range, C compare, RangeSize<R> depth) {
|
||||
if (range.size() <= 10) {
|
||||
__octa_insort(range, compare);
|
||||
template<typename _R, typename _C>
|
||||
void __octa_introloop(_R __range, _C __compare, RangeSize<_R> __depth) {
|
||||
if (__range.size() <= 10) {
|
||||
__octa_insort(__range, __compare);
|
||||
return;
|
||||
}
|
||||
if (depth == 0) {
|
||||
__octa_heapsort(range, compare);
|
||||
if (__depth == 0) {
|
||||
__octa_heapsort(__range, __compare);
|
||||
return;
|
||||
}
|
||||
RangeReference<R> p = range[range.size() / 2];
|
||||
swap(p, range.back());
|
||||
R r = partition(range, __OctaUnaryCompare<decltype(p), C>{ p, compare });
|
||||
R l = range.slice(0, range.size() - r.size());
|
||||
swap(r.front(), r.back());
|
||||
__octa_introloop(l, compare, depth - 1);
|
||||
__octa_introloop(r, compare, depth - 1);
|
||||
octa::RangeReference<_R> __p = __range[__range.size() / 2];
|
||||
octa::swap(__p, __range.back());
|
||||
_R __r = octa::partition(__range,
|
||||
__OctaUnaryCompare<decltype(__p), _C>{ __p, __compare });
|
||||
_R __l = __range.slice(0, __range.size() - __r.size());
|
||||
octa::swap(__r.front(), __r.back());
|
||||
__octa_introloop(__l, __compare, __depth - 1);
|
||||
__octa_introloop(__r, __compare, __depth - 1);
|
||||
}
|
||||
|
||||
template<typename R, typename C>
|
||||
void __octa_introsort(R range, C compare) {
|
||||
__octa_introloop(range, compare, RangeSize<R>(2
|
||||
* (log(range.size()) / log(2))));
|
||||
template<typename _R, typename _C>
|
||||
void __octa_introsort(_R __range, _C __compare) {
|
||||
__octa_introloop(__range, __compare, octa::RangeSize<_R>(2
|
||||
* (log(__range.size()) / log(2))));
|
||||
}
|
||||
|
||||
template<typename R, typename C>
|
||||
void sort(R range, C compare) {
|
||||
__octa_introsort(range, compare);
|
||||
template<typename _R, typename _C>
|
||||
void sort(_R __range, _C __compare) {
|
||||
__octa_introsort(__range, __compare);
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
void sort(R range) {
|
||||
sort(range, 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) {
|
||||
return (a < b) ? a : 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) {
|
||||
return compare(a, b) ? a : b;
|
||||
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) {
|
||||
return (a < b) ? b : a;
|
||||
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) {
|
||||
return compare(a, b) ? b : a;
|
||||
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;
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (min(r.front(), range.front()) == range.front())
|
||||
r = range;
|
||||
return r;
|
||||
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;
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (min(r.front(), range.front(), compare) == range.front())
|
||||
r = range;
|
||||
return r;
|
||||
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;
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (max(r.front(), range.front()) == range.front())
|
||||
r = range;
|
||||
return r;
|
||||
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;
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (max(r.front(), range.front(), compare) == range.front())
|
||||
r = range;
|
||||
return r;
|
||||
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;
|
||||
}
|
||||
|
||||
using std::initializer_list;
|
||||
|
||||
template<typename T>
|
||||
inline T min(initializer_list<T> il) {
|
||||
return min_element(each(il)).front();
|
||||
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(initializer_list<T> il, C compare) {
|
||||
return min_element(each(il), compare).front();
|
||||
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(initializer_list<T> il) {
|
||||
return max_element(each(il)).front();
|
||||
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(initializer_list<T> il, C compare) {
|
||||
return max_element(each(il), compare).front();
|
||||
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 max(T(lo), 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 max(T(lo), 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) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
func(range.front());
|
||||
return move(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) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (!pred(range.front())) return false;
|
||||
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) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (pred(range.front())) return true;
|
||||
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) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (pred(range.front())) return false;
|
||||
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) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (range.front() == 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;
|
||||
return __range;
|
||||
}
|
||||
|
||||
template<typename R, typename P>
|
||||
R find_if(R range, P pred) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (pred(range.front()))
|
||||
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;
|
||||
return __range;
|
||||
}
|
||||
|
||||
template<typename R, typename P>
|
||||
R find_if_not(R range, P pred) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (!pred(range.front()))
|
||||
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;
|
||||
return __range;
|
||||
}
|
||||
|
||||
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 _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;
|
||||
for (; !range.empty(); range.pop_front())
|
||||
if (pred(range.front()))
|
||||
++ret;
|
||||
return ret;
|
||||
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;
|
||||
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;
|
||||
for (; !__range.empty(); __range.pop_front())
|
||||
if (!__pred(__range.front()))
|
||||
++__ret;
|
||||
return __ret;
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
bool equal(R range1, R range2) {
|
||||
for (; !range1.empty(); range1.pop_front()) {
|
||||
if (range2.empty() || (range1.front() != range2.front()))
|
||||
template<typename _R>
|
||||
bool equal(_R __range1, _R __range2) {
|
||||
for (; !__range1.empty(); __range1.pop_front()) {
|
||||
if (__range2.empty() || (__range1.front() != __range2.front()))
|
||||
return false;
|
||||
range2.pop_front();
|
||||
__range2.pop_front();
|
||||
}
|
||||
return range2.empty();
|
||||
return __range2.empty();
|
||||
}
|
||||
|
||||
/* algos that modify ranges or work with output ranges */
|
||||
|
||||
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>
|
||||
_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) {
|
||||
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(_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) {
|
||||
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) {
|
||||
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) {
|
||||
for (; !irange.empty(); irange.pop_front())
|
||||
orange.put(move(irange.front()));
|
||||
return 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) {
|
||||
while (!range.empty()) {
|
||||
swap(range.front(), range.back());
|
||||
range.pop_front();
|
||||
range.pop_back();
|
||||
template<typename _R>
|
||||
void reverse(_R __range) {
|
||||
while (!__range.empty()) {
|
||||
octa::swap(__range.front(), __range.back());
|
||||
__range.pop_front();
|
||||
__range.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
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 _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) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
range.front() = 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) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
range.front() = 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>
|
||||
Pair<R1, R2> swap_ranges(R1 range1, R2 range2) {
|
||||
while (!range1.empty() && !range2.empty()) {
|
||||
swap(range1.front(), range2.front());
|
||||
range1.pop_front();
|
||||
range2.pop_front();
|
||||
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();
|
||||
__range2.pop_front();
|
||||
}
|
||||
return Pair<R1, R2>(range1, range2);
|
||||
return octa::Pair<_R1, _R2>(__range1, __range2);
|
||||
}
|
||||
|
||||
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>
|
||||
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) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
init = init + range.front();
|
||||
return 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) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
init = func(init, range.front());
|
||||
return init;
|
||||
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) {
|
||||
for (; !range.empty(); range.pop_back())
|
||||
init = init + range.back();
|
||||
return 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) {
|
||||
for (; !range.empty(); range.pop_back())
|
||||
init = func(init, range.back());
|
||||
return init;
|
||||
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>, RangeCategory<T>, R, R, RangeSize<T>
|
||||
MapRange<_T, _R>, octa::RangeCategory<_T>, _R, _R, octa::RangeSize<_T>
|
||||
> {
|
||||
private:
|
||||
T p_range;
|
||||
Function<R(RangeReference<T>)> p_func;
|
||||
_T __range;
|
||||
octa::Function<_R(octa::RangeReference<_T>)> __func;
|
||||
|
||||
public:
|
||||
MapRange(): p_range(), p_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) {}
|
||||
MapRange(MapRange &&it): p_range(move(it.p_range)), p_func(move(it.p_func)) {}
|
||||
MapRange(): __range(), __func() {}
|
||||
template<typename _F>
|
||||
MapRange(const _T &__range, const _F &__func):
|
||||
__range(__range), __func(__func) {}
|
||||
MapRange(const MapRange &__it):
|
||||
__range(__it.__range), __func(__it.__func) {}
|
||||
MapRange(MapRange &&__it):
|
||||
__range(move(__it.__range)), __func(move(__it.__func)) {}
|
||||
|
||||
MapRange &operator=(const MapRange &v) {
|
||||
p_range = v.p_range;
|
||||
p_func = v.p_func;
|
||||
MapRange &operator=(const MapRange &__v) {
|
||||
__range = __v.__range;
|
||||
__func = __v.__func;
|
||||
return *this;
|
||||
}
|
||||
MapRange &operator=(MapRange &&v) {
|
||||
p_range = move(v.p_range);
|
||||
p_func = move(v.p_func);
|
||||
MapRange &operator=(MapRange &&__v) {
|
||||
__range = move(__v.__range);
|
||||
__func = move(__v.__func);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const { return p_range.empty(); }
|
||||
RangeSize<T> size() const { return p_range.size(); }
|
||||
bool empty() const { return __range.empty(); }
|
||||
octa::RangeSize<_T> size() const { return __range.size(); }
|
||||
|
||||
bool equals_front(const MapRange &range) const {
|
||||
return p_range.equals_front(range.p_range);
|
||||
bool equals_front(const MapRange &__r) const {
|
||||
return __range.equals_front(__r.__range);
|
||||
}
|
||||
bool equals_back(const MapRange &range) const {
|
||||
return p_range.equals_front(range.p_range);
|
||||
bool equals_back(const MapRange &__r) const {
|
||||
return __range.equals_front(__r.__range);
|
||||
}
|
||||
|
||||
RangeDifference<T> distance_front(const MapRange &range) const {
|
||||
return p_range.distance_front(range.p_range);
|
||||
octa::RangeDifference<_T> distance_front(const MapRange &__r) const {
|
||||
return __range.distance_front(__r.__range);
|
||||
}
|
||||
RangeDifference<T> distance_back(const MapRange &range) const {
|
||||
return p_range.distance_back(range.p_range);
|
||||
octa::RangeDifference<_T> distance_back(const MapRange &__r) const {
|
||||
return __range.distance_back(__r.__range);
|
||||
}
|
||||
|
||||
bool pop_front() { return p_range.pop_front(); }
|
||||
bool pop_back() { return p_range.pop_back(); }
|
||||
bool pop_front() { return __range.pop_front(); }
|
||||
bool pop_back() { return __range.pop_back(); }
|
||||
|
||||
bool push_front() { return p_range.pop_front(); }
|
||||
bool push_back() { return p_range.push_back(); }
|
||||
bool push_front() { return __range.pop_front(); }
|
||||
bool push_back() { return __range.push_back(); }
|
||||
|
||||
RangeSize<T> pop_front_n(RangeSize<T> n) { p_range.pop_front_n(n); }
|
||||
RangeSize<T> pop_back_n(RangeSize<T> n) { p_range.pop_back_n(n); }
|
||||
|
||||
RangeSize<T> push_front_n(RangeSize<T> n) { return p_range.push_front_n(n); }
|
||||
RangeSize<T> push_back_n(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 operator[](RangeSize<T> idx) const {
|
||||
return p_func(p_range[idx]);
|
||||
octa::RangeSize<_T> pop_front_n(octa::RangeSize<_T> __n) {
|
||||
__range.pop_front_n(__n);
|
||||
}
|
||||
octa::RangeSize<_T> pop_back_n(octa::RangeSize<_T> __n) {
|
||||
__range.pop_back_n(__n);
|
||||
}
|
||||
|
||||
MapRange<T, R> slice(RangeSize<T> start, RangeSize<T> end) {
|
||||
return MapRange<T, R>(p_range.slice(start, end), p_func);
|
||||
octa::RangeSize<_T> push_front_n(octa::RangeSize<_T> __n) {
|
||||
return __range.push_front_n(__n);
|
||||
}
|
||||
octa::RangeSize<_T> push_back_n(octa::RangeSize<_T> __n) {
|
||||
return __range.push_back_n(__n);
|
||||
}
|
||||
|
||||
_R front() const { return __func(__range.front()); }
|
||||
_R back() const { return __func(__range.back()); }
|
||||
|
||||
_R operator[](octa::RangeSize<_T> __idx) const {
|
||||
return __func(__range[__idx]);
|
||||
}
|
||||
|
||||
MapRange<_T, _R> slice(octa::RangeSize<_T> __start,
|
||||
octa::RangeSize<_T> __end) {
|
||||
return MapRange<_T, _R>(__range.slice(__start, __end), __func);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename R, typename F>
|
||||
using __OctaMapReturnType = decltype(declval<F>()(declval<RangeReference<R>>()));
|
||||
template<typename _R, typename _F> using __OctaMapReturnType
|
||||
= decltype(declval<_F>()(octa::declval<octa::RangeReference<_R>>()));
|
||||
|
||||
template<typename R, typename F>
|
||||
MapRange<R, __OctaMapReturnType<R, F>> map(R range, F func) {
|
||||
return MapRange<R, __OctaMapReturnType<R, F>>(range, func);
|
||||
template<typename _R, typename _F>
|
||||
MapRange<_R, __OctaMapReturnType<_R, _F>> map(_R __range, _F __func) {
|
||||
return octa::MapRange<_R, __OctaMapReturnType<_R, _F>>(__range, __func);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
struct FilterRange: InputRange<
|
||||
FilterRange<T>, CommonType<RangeCategory<T>, ForwardRangeTag>,
|
||||
RangeValue<T>, RangeReference<T>, RangeSize<T>
|
||||
FilterRange<_T>, octa::CommonType<octa::RangeCategory<_T>,
|
||||
octa::ForwardRangeTag>,
|
||||
octa::RangeValue<_T>, octa::RangeReference<_T>, octa::RangeSize<_T>
|
||||
> {
|
||||
private:
|
||||
T p_range;
|
||||
Function<bool(RangeReference<T>)> p_pred;
|
||||
_T __range;
|
||||
octa::Function<bool(octa::RangeReference<_T>)> __pred;
|
||||
|
||||
void advance_valid() {
|
||||
while (!p_range.empty() && !p_pred(front())) p_range.pop_front();
|
||||
while (!__range.empty() && !__pred(front())) __range.pop_front();
|
||||
}
|
||||
|
||||
public:
|
||||
FilterRange(): p_range(), p_pred() {}
|
||||
FilterRange(): __range(), __pred() {}
|
||||
|
||||
template<typename P>
|
||||
FilterRange(const T &range, const P &pred): p_range(range),
|
||||
p_pred(pred) {
|
||||
template<typename _P>
|
||||
FilterRange(const _T &__range, const _P &__pred): __range(__range),
|
||||
__pred(__pred) {
|
||||
advance_valid();
|
||||
}
|
||||
FilterRange(const FilterRange &it): p_range(it.p_range),
|
||||
p_pred(it.p_pred) {
|
||||
FilterRange(const FilterRange &__it): __range(__it.__range),
|
||||
__pred(__it.__pred) {
|
||||
advance_valid();
|
||||
}
|
||||
FilterRange(FilterRange &&it): p_range(move(it.p_range)),
|
||||
p_pred(move(it.p_pred)) {
|
||||
FilterRange(FilterRange &&__it): __range(move(__it.__range)),
|
||||
__pred(move(__it.__pred)) {
|
||||
advance_valid();
|
||||
}
|
||||
|
||||
FilterRange &operator=(const FilterRange &v) {
|
||||
p_range = v.p_range;
|
||||
p_pred = v.p_pred;
|
||||
FilterRange &operator=(const FilterRange &__v) {
|
||||
__range = __v.__range;
|
||||
__pred = __v.__pred;
|
||||
advance_valid();
|
||||
return *this;
|
||||
}
|
||||
FilterRange &operator=(FilterRange &&v) {
|
||||
p_range = move(v.p_range);
|
||||
p_pred = move(v.p_pred);
|
||||
FilterRange &operator=(FilterRange &&__v) {
|
||||
__range = move(__v.__range);
|
||||
__pred = move(__v.__pred);
|
||||
advance_valid();
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const { return p_range.empty(); }
|
||||
bool empty() const { return __range.empty(); }
|
||||
|
||||
bool equals_front(const FilterRange &range) const {
|
||||
return p_range.equals_front(range.p_range);
|
||||
bool equals_front(const FilterRange &__r) const {
|
||||
return __range.equals_front(__r.__range);
|
||||
}
|
||||
|
||||
bool pop_front() {
|
||||
bool ret = p_range.pop_front();
|
||||
bool __ret = __range.pop_front();
|
||||
advance_valid();
|
||||
return ret;
|
||||
return __ret;
|
||||
}
|
||||
bool push_front() {
|
||||
T tmp = p_range;
|
||||
if (!tmp.push_front()) return false;
|
||||
while (!pred(tmp.front()))
|
||||
if (!tmp.push_front())
|
||||
_T __tmp = __range;
|
||||
if (!__tmp.push_front()) return false;
|
||||
while (!pred(__tmp.front()))
|
||||
if (!__tmp.push_front())
|
||||
return false;
|
||||
p_range = tmp;
|
||||
__range = __tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
RangeReference<T> front() const { return p_range.front(); }
|
||||
octa::RangeReference<_T> front() const { return __range.front(); }
|
||||
};
|
||||
|
||||
template<typename R, typename P>
|
||||
FilterRange<R> filter(R range, P pred) {
|
||||
return FilterRange<R>(range, pred);
|
||||
template<typename _R, typename _P>
|
||||
FilterRange<_R> filter(_R __range, _P __pred) {
|
||||
return octa::FilterRange<_R>(__range, __pred);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
62
octa/array.h
62
octa/array.h
|
@ -13,55 +13,55 @@
|
|||
#include "octa/string.h"
|
||||
|
||||
namespace octa {
|
||||
template<typename T, size_t N>
|
||||
template<typename _T, size_t _N>
|
||||
struct Array {
|
||||
typedef size_t SizeType;
|
||||
typedef ptrdiff_t DiffType;
|
||||
typedef T ValType;
|
||||
typedef T &RefType;
|
||||
typedef const T &ConstRefType;
|
||||
typedef T *PtrType;
|
||||
typedef const T *ConstPtrType;
|
||||
typedef PointerRange< T> RangeType;
|
||||
typedef PointerRange<const T> ConstRangeType;
|
||||
typedef size_t SizeType;
|
||||
typedef ptrdiff_t DiffType;
|
||||
typedef _T ValType;
|
||||
typedef _T &RefType;
|
||||
typedef const _T &ConstRefType;
|
||||
typedef _T *PtrType;
|
||||
typedef const _T *ConstPtrType;
|
||||
typedef PointerRange< _T> RangeType;
|
||||
typedef PointerRange<const _T> ConstRangeType;
|
||||
|
||||
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 __buf[__i]; }
|
||||
const _T &operator[](size_t __i) const { return __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 __buf[__i]; }
|
||||
const _T &at(size_t __i) const { return __buf[__i]; }
|
||||
|
||||
T &front() { return p_buf[0]; }
|
||||
const T &front() const { return p_buf[0]; }
|
||||
_T &front() { return __buf[0]; }
|
||||
const _T &front() const { return __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 __buf[(_N > 0) ? (_N - 1) : 0]; }
|
||||
const _T &back() const { return __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 >= &__buf[0] && __ptr < &__buf[_N];
|
||||
}
|
||||
|
||||
T *data() { return p_buf; }
|
||||
const T *data() const { return p_buf; }
|
||||
_T *data() { return __buf; }
|
||||
const _T *data() const { return __buf; }
|
||||
|
||||
RangeType each() {
|
||||
return PointerRange<T>(p_buf, p_buf + N);
|
||||
return octa::PointerRange<_T>(__buf, __buf + _N);
|
||||
}
|
||||
ConstRangeType each() const {
|
||||
return PointerRange<const T>(p_buf, p_buf + N);
|
||||
return octa::PointerRange<const _T>(__buf, __buf + _N);
|
||||
}
|
||||
|
||||
void swap(Array &v) {
|
||||
swap_ranges(each(), v.each());
|
||||
void swap(Array &__v) {
|
||||
octa::swap_ranges(each(), __v.each());
|
||||
}
|
||||
|
||||
T p_buf[(N > 0) ? N : 1];
|
||||
_T __buf[(_N > 0) ? _N : 1];
|
||||
};
|
||||
}
|
||||
|
||||
|
|
1402
octa/atomic.h
1402
octa/atomic.h
File diff suppressed because it is too large
Load diff
|
@ -14,12 +14,14 @@
|
|||
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 { return x op y; } \
|
||||
typedef T FirstArgType; \
|
||||
typedef T SecondArgType; \
|
||||
typedef rettype ResultType; \
|
||||
#define __OCTA_DEFINE_BINARY_OP(_name, _op, _rettype) \
|
||||
template<typename _T> struct _name { \
|
||||
_rettype operator()(const _T &__x, const _T &__y) const { \
|
||||
return __x _op __y; \
|
||||
} \
|
||||
typedef _T FirstArgType; \
|
||||
typedef _T SecondArgType; \
|
||||
typedef _rettype ResultType; \
|
||||
};
|
||||
|
||||
__OCTA_DEFINE_BINARY_OP(Less, <, bool)
|
||||
|
@ -30,78 +32,78 @@ namespace octa {
|
|||
__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 ArgType;
|
||||
template<typename _T> struct LogicalNot {
|
||||
bool operator()(const _T &__x) const { return !__x; }
|
||||
typedef _T ArgType;
|
||||
typedef bool ResultType;
|
||||
};
|
||||
|
||||
template<typename T> struct Negate {
|
||||
bool operator()(const T &x) const { return -x; }
|
||||
typedef T ArgType;
|
||||
typedef T ResultType;
|
||||
template<typename _T> struct Negate {
|
||||
bool operator()(const _T &__x) const { return -__x; }
|
||||
typedef _T ArgType;
|
||||
typedef _T ResultType;
|
||||
};
|
||||
|
||||
template<typename T> struct BinaryNegate {
|
||||
typedef typename T::FirstArgType FirstArgType;
|
||||
typedef typename T::SecondArgType SecondArgType;
|
||||
template<typename _T> struct BinaryNegate {
|
||||
typedef typename _T::FirstArgType FirstArgType;
|
||||
typedef typename _T::SecondArgType SecondArgType;
|
||||
typedef bool ResultType;
|
||||
|
||||
explicit BinaryNegate(const T &f): p_fn(f) {}
|
||||
explicit BinaryNegate(const _T &__f): __fn(__f) {}
|
||||
|
||||
bool operator()(const FirstArgType &x,
|
||||
const SecondArgType &y) {
|
||||
return !p_fn(x, y);
|
||||
bool operator()(const FirstArgType &__x,
|
||||
const SecondArgType &__y) {
|
||||
return !__fn(__x, __y);
|
||||
}
|
||||
private:
|
||||
T p_fn;
|
||||
_T __fn;
|
||||
};
|
||||
|
||||
template<typename T> struct UnaryNegate {
|
||||
typedef typename T::ArgType ArgType;
|
||||
template<typename _T> struct UnaryNegate {
|
||||
typedef typename _T::ArgType ArgType;
|
||||
typedef bool ResultType;
|
||||
|
||||
explicit UnaryNegate(const T &f): p_fn(f) {}
|
||||
bool operator()(const ArgType &x) {
|
||||
return !p_fn(x);
|
||||
explicit UnaryNegate(const _T &__f): __fn(__f) {}
|
||||
bool operator()(const ArgType &__x) {
|
||||
return !__fn(__x);
|
||||
}
|
||||
private:
|
||||
T p_fn;
|
||||
_T __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;
|
||||
|
||||
template<typename T> struct __OctaHashBase {
|
||||
typedef T ArgType;
|
||||
template<typename _T> struct __OctaHashBase {
|
||||
typedef _T ArgType;
|
||||
typedef size_t ResultType;
|
||||
|
||||
size_t operator()(T v) const {
|
||||
return (size_t)v;
|
||||
size_t operator()(_T __v) const {
|
||||
return size_t(__v);
|
||||
}
|
||||
};
|
||||
|
||||
#define __OCTA_HASH_BASIC(T) template<> struct Hash<T>: __OctaHashBase<T> {};
|
||||
#define __OCTA_HASH_BASIC(_T) template<> struct Hash<_T>: __OctaHashBase<_T> {};
|
||||
|
||||
__OCTA_HASH_BASIC(bool)
|
||||
__OCTA_HASH_BASIC(char)
|
||||
|
@ -119,69 +121,69 @@ namespace octa {
|
|||
|
||||
#undef __OCTA_HASH_BASIC
|
||||
|
||||
static inline size_t __octa_mem_hash(const void *p, size_t l) {
|
||||
const uchar *d = (const uchar *)p;
|
||||
size_t h = 5381;
|
||||
for (size_t i = 0; i < l; ++i) h = ((h << 5) + h) ^ d[i];
|
||||
return h;
|
||||
static inline size_t __octa_mem_hash(const void *__p, size_t __l) {
|
||||
const uchar *__d = (const uchar *)__p;
|
||||
size_t __h = 5381;
|
||||
for (size_t __i = 0; __i < __l; ++__i) __h = ((__h << 5) + __h) ^ __d[__i];
|
||||
return __h;
|
||||
}
|
||||
|
||||
template<typename T, size_t = sizeof(T) / sizeof(size_t)>
|
||||
template<typename _T, size_t = sizeof(_T) / sizeof(size_t)>
|
||||
struct __OctaScalarHash;
|
||||
|
||||
template<typename T> struct __OctaScalarHash<T, 0> {
|
||||
typedef T ArgType;
|
||||
template<typename _T> struct __OctaScalarHash<_T, 0> {
|
||||
typedef _T ArgType;
|
||||
typedef size_t ResultType;
|
||||
|
||||
size_t operator()(T v) const {
|
||||
union { T v; size_t h; } u;
|
||||
u.h = 0;
|
||||
u.v = v;
|
||||
return u.h;
|
||||
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 __OctaScalarHash<T, 1> {
|
||||
typedef T ArgType;
|
||||
template<typename _T> struct __OctaScalarHash<_T, 1> {
|
||||
typedef _T ArgType;
|
||||
typedef size_t ResultType;
|
||||
|
||||
size_t operator()(T v) const {
|
||||
union { T v; size_t h; } u;
|
||||
u.v = v;
|
||||
return u.h;
|
||||
size_t operator()(_T __v) const {
|
||||
union { _T __v; size_t __h; } __u;
|
||||
__u.__v = __v;
|
||||
return __u.__h;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct __OctaScalarHash<T, 2> {
|
||||
typedef T ArgType;
|
||||
template<typename _T> struct __OctaScalarHash<_T, 2> {
|
||||
typedef _T ArgType;
|
||||
typedef size_t ResultType;
|
||||
|
||||
size_t operator()(T v) const {
|
||||
union { T v; struct { size_t h1, h2; }; } u;
|
||||
u.v = v;
|
||||
return __octa_mem_hash((const void *)&u, sizeof(u));
|
||||
size_t operator()(_T __v) const {
|
||||
union { _T __v; struct { size_t __h1, __h2; }; } __u;
|
||||
__u.__v = __v;
|
||||
return __octa_mem_hash((const void *)&__u, sizeof(__u));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct __OctaScalarHash<T, 3> {
|
||||
typedef T ArgType;
|
||||
template<typename _T> struct __OctaScalarHash<_T, 3> {
|
||||
typedef _T ArgType;
|
||||
typedef size_t ResultType;
|
||||
|
||||
size_t operator()(T v) const {
|
||||
union { T v; struct { size_t h1, h2, h3; }; } u;
|
||||
u.v = v;
|
||||
return __octa_mem_hash((const void *)&u, sizeof(u));
|
||||
size_t operator()(_T __v) const {
|
||||
union { _T __v; struct { size_t __h1, __h2, __h3; }; } __u;
|
||||
__u.__v = __v;
|
||||
return __octa_mem_hash((const void *)&__u, sizeof(__u));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct __OctaScalarHash<T, 4> {
|
||||
typedef T ArgType;
|
||||
template<typename _T> struct __OctaScalarHash<_T, 4> {
|
||||
typedef _T ArgType;
|
||||
typedef size_t ResultType;
|
||||
|
||||
size_t operator()(T v) const {
|
||||
union { T v; struct { size_t h1, h2, h3, h4; }; } u;
|
||||
u.v = v;
|
||||
return __octa_mem_hash((const void *)&u, sizeof(u));
|
||||
size_t operator()(_T __v) const {
|
||||
union { _T __v; struct { size_t __h1, __h2, __h3, __h4; }; } __u;
|
||||
__u.__v = __v;
|
||||
return __octa_mem_hash((const void *)&__u, sizeof(__u));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -189,146 +191,146 @@ namespace octa {
|
|||
template<> struct Hash<ullong>: __OctaScalarHash<ullong> {};
|
||||
|
||||
template<> struct Hash<float>: __OctaScalarHash<float> {
|
||||
size_t operator()(float v) const {
|
||||
if (v == 0) return 0;
|
||||
return __OctaScalarHash<float>::operator()(v);
|
||||
size_t operator()(float __v) const {
|
||||
if (__v == 0) return 0;
|
||||
return __OctaScalarHash<float>::operator()(__v);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct Hash<double>: __OctaScalarHash<double> {
|
||||
size_t operator()(double v) const {
|
||||
if (v == 0) return 0;
|
||||
return __OctaScalarHash<double>::operator()(v);
|
||||
size_t operator()(double __v) const {
|
||||
if (__v == 0) return 0;
|
||||
return __OctaScalarHash<double>::operator()(__v);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct Hash<ldouble>: __OctaScalarHash<ldouble> {
|
||||
size_t operator()(ldouble v) const {
|
||||
if (v == 0) return 0;
|
||||
size_t operator()(ldouble __v) const {
|
||||
if (__v == 0) return 0;
|
||||
#ifdef __i386__
|
||||
union { ldouble v; struct { size_t h1, h2, h3, h4; }; } u;
|
||||
u.h1 = u.h2 = u.h3 = u.h4 = 0;
|
||||
u.v = v;
|
||||
return (u.h1 ^ u.h2 ^ u.h3 ^ u.h4);
|
||||
union { ldouble __v; struct { size_t __h1, __h2, __h3, __h4; }; } __u;
|
||||
__u.__h1 = __u.__h2 = __u.__h3 = __u.__h4 = 0;
|
||||
__u.__v = __v;
|
||||
return (__u.__h1 ^ __u.__h2 ^ __u.__h3 ^ __u.__h4);
|
||||
#else
|
||||
#ifdef __x86_64__
|
||||
union { ldouble v; struct { size_t h1, h2; }; } u;
|
||||
u.h1 = u.h2 = 0;
|
||||
u.v = v;
|
||||
return (u.h1 ^ u.h2);
|
||||
union { ldouble __v; struct { size_t __h1, __h2; }; } __u;
|
||||
__u.__h1 = __u.__h2 = 0;
|
||||
__u.__v = __v;
|
||||
return (__u.__h1 ^ __u.__h2);
|
||||
#else
|
||||
return __OctaScalarHash<ldouble>::operator()(v);
|
||||
return __OctaScalarHash<ldouble>::operator()(__v);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct Hash<T *> {
|
||||
typedef T *ArgType;
|
||||
template<typename _T> struct Hash<_T *> {
|
||||
typedef _T *ArgType;
|
||||
typedef size_t ResultType;
|
||||
|
||||
size_t operator()(T *v) const {
|
||||
union { T *v; size_t h; } u;
|
||||
u.v = v;
|
||||
return __octa_mem_hash((const void *)&u, sizeof(u));
|
||||
size_t operator()(_T *__v) const {
|
||||
union { _T *__v; size_t __h; } __u;
|
||||
__u.__v = __v;
|
||||
return __octa_mem_hash((const void *)&__u, sizeof(__u));
|
||||
}
|
||||
};
|
||||
|
||||
/* 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): __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 *__ptr; }
|
||||
_T &get() const { return *__ptr; }
|
||||
|
||||
private:
|
||||
T *p_ptr;
|
||||
_T *__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 */
|
||||
|
||||
template<typename, typename> struct __OctaMemTypes;
|
||||
template<typename T, typename R, typename ...A>
|
||||
struct __OctaMemTypes<T, R(A...)> {
|
||||
typedef R ResultType;
|
||||
typedef T ArgType;
|
||||
template<typename _T, typename _R, typename ..._A>
|
||||
struct __OctaMemTypes<_T, _R(_A...)> {
|
||||
typedef _R ResultType;
|
||||
typedef _T ArgType;
|
||||
};
|
||||
template<typename T, typename R, typename A>
|
||||
struct __OctaMemTypes<T, R(A)> {
|
||||
typedef R ResultType;
|
||||
typedef T FirstArgType;
|
||||
typedef A SecondArgType;
|
||||
template<typename _T, typename _R, typename _A>
|
||||
struct __OctaMemTypes<_T, _R(_A)> {
|
||||
typedef _R ResultType;
|
||||
typedef _T FirstArgType;
|
||||
typedef _A SecondArgType;
|
||||
};
|
||||
template<typename T, typename R, typename ...A>
|
||||
struct __OctaMemTypes<T, R(A...) const> {
|
||||
typedef R ResultType;
|
||||
typedef const T ArgType;
|
||||
template<typename _T, typename _R, typename ..._A>
|
||||
struct __OctaMemTypes<_T, _R(_A...) const> {
|
||||
typedef _R ResultType;
|
||||
typedef const _T ArgType;
|
||||
};
|
||||
template<typename T, typename R, typename A>
|
||||
struct __OctaMemTypes<T, R(A) const> {
|
||||
typedef R ResultType;
|
||||
typedef const T FirstArgType;
|
||||
typedef A SecondArgType;
|
||||
template<typename _T, typename _R, typename _A>
|
||||
struct __OctaMemTypes<_T, _R(_A) const> {
|
||||
typedef _R ResultType;
|
||||
typedef const _T FirstArgType;
|
||||
typedef _A SecondArgType;
|
||||
};
|
||||
|
||||
template<typename R, typename T>
|
||||
class __OctaMemFn: __OctaMemTypes<T, R> {
|
||||
R T::*p_ptr;
|
||||
template<typename _R, typename _T>
|
||||
class __OctaMemFn: __OctaMemTypes<_T, _R> {
|
||||
_R _T::*__ptr;
|
||||
public:
|
||||
__OctaMemFn(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)...);
|
||||
__OctaMemFn(_R _T::*__ptr): __ptr(__ptr) {}
|
||||
template<typename... _A>
|
||||
auto operator()(_T &__obj, _A &&...__args) ->
|
||||
decltype(((__obj).*(__ptr))(forward<_A>(__args)...)) {
|
||||
return ((__obj).*(__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).*(__ptr))(forward<_A>(__args)...)) const {
|
||||
return ((__obj).*(__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)->*(__ptr))(forward<_A>(__args)...)) {
|
||||
return ((__obj)->*(__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)->*(__ptr))(forward<_A>(__args)...)) const {
|
||||
return ((__obj)->*(__ptr))(forward<_A>(__args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename R, typename T>
|
||||
__OctaMemFn<R, T> mem_fn(R T:: *ptr) {
|
||||
return __OctaMemFn<R, T>(ptr);
|
||||
template<typename _R, typename _T>
|
||||
__OctaMemFn<_R, _T> mem_fn(_R _T:: *__ptr) {
|
||||
return __OctaMemFn<_R, _T>(__ptr);
|
||||
}
|
||||
|
||||
/* function impl
|
||||
|
@ -338,296 +340,303 @@ namespace octa {
|
|||
template<typename> struct Function;
|
||||
|
||||
struct __OctaFunctorData {
|
||||
void *p1, *p2;
|
||||
void *__p1, *__p2;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
struct __OctaFunctorInPlace {
|
||||
static constexpr bool value = sizeof(T) <= sizeof(__OctaFunctorData)
|
||||
&& (alignof(__OctaFunctorData) % alignof(T)) == 0
|
||||
&& octa::IsMoveConstructible<T>::value;
|
||||
static constexpr bool value = sizeof(_T) <= sizeof(__OctaFunctorData)
|
||||
&& (alignof(__OctaFunctorData) % alignof(_T)) == 0
|
||||
&& octa::IsMoveConstructible<_T>::value;
|
||||
};
|
||||
|
||||
template<typename T, typename E = void>
|
||||
template<typename _T, typename _E = void>
|
||||
struct __OctaFunctorDataManager {
|
||||
template<typename R, typename ...A>
|
||||
static R call(const __OctaFunctorData &s, A ...args) {
|
||||
return ((T &)s)(forward<A>(args)...);
|
||||
template<typename _R, typename ..._A>
|
||||
static _R __call(const __OctaFunctorData &__s, _A ...__args) {
|
||||
return ((_T &)__s)(octa::forward<_A>(__args)...);
|
||||
}
|
||||
|
||||
static void store_f(__OctaFunctorData &s, T v) {
|
||||
new (&get_ref(s)) T(forward<T>(v));
|
||||
static void __store_f(__OctaFunctorData &__s, _T __v) {
|
||||
new (&__get_ref(__s)) _T(octa::forward<_T>(__v));
|
||||
}
|
||||
|
||||
static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) {
|
||||
new (&get_ref(lhs)) T(move(get_ref(rhs)));
|
||||
static void __move_f(__OctaFunctorData &__lhs, __OctaFunctorData &&__rhs) {
|
||||
new (&__get_ref(__lhs)) _T(octa::move(__get_ref(__rhs)));
|
||||
}
|
||||
|
||||
static void destroy_f(__OctaFunctorData &s) {
|
||||
get_ref(s).~T();
|
||||
static void __destroy_f(__OctaFunctorData &__s) {
|
||||
__get_ref(__s).~_T();
|
||||
}
|
||||
|
||||
static T &get_ref(const __OctaFunctorData &s) {
|
||||
return (T &)s;
|
||||
static _T &__get_ref(const __OctaFunctorData &__s) {
|
||||
return (_T &)__s;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct __OctaFunctorDataManager<T, EnableIf<!__OctaFunctorInPlace<T>::value>> {
|
||||
template<typename R, typename ...A>
|
||||
static R call(const __OctaFunctorData &s, A ...args) {
|
||||
return (*(T *&)s)(forward<A>(args)...);
|
||||
template<typename _T>
|
||||
struct __OctaFunctorDataManager<_T, EnableIf<!__OctaFunctorInPlace<_T>::value>> {
|
||||
template<typename _R, typename ..._A>
|
||||
static _R __call(const __OctaFunctorData &__s, _A ...__args) {
|
||||
return (*(_T *&)__s)(octa::forward<_A>(__args)...);
|
||||
}
|
||||
|
||||
static void store_f(__OctaFunctorData &s, T v) {
|
||||
new (&get_ptr_ref(s)) T *(new T(forward<T>(v)));
|
||||
static void __store_f(__OctaFunctorData &__s, _T __v) {
|
||||
new (&__get_ptr_ref(__s)) _T *(new _T(octa::forward<_T>(__v)));
|
||||
}
|
||||
|
||||
static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) {
|
||||
new (&get_ptr_ref(lhs)) T *(get_ptr_ref(rhs));
|
||||
get_ptr_ref(rhs) = nullptr;
|
||||
static void __move_f(__OctaFunctorData &__lhs, __OctaFunctorData &&__rhs) {
|
||||
new (&__get_ptr_ref(__lhs)) _T *(__get_ptr_ref(__rhs));
|
||||
__get_ptr_ref(__rhs) = nullptr;
|
||||
}
|
||||
|
||||
static void destroy_f(__OctaFunctorData &s) {
|
||||
T *&ptr = get_ptr_ref(s);
|
||||
if (!ptr) return;
|
||||
delete ptr;
|
||||
ptr = nullptr;
|
||||
static void __destroy_f(__OctaFunctorData &__s) {
|
||||
_T *&__ptr = __get_ptr_ref(__s);
|
||||
if (!__ptr) return;
|
||||
delete __ptr;
|
||||
__ptr = nullptr;
|
||||
}
|
||||
|
||||
static T &get_ref(const __OctaFunctorData &s) {
|
||||
return *get_ptr_ref(s);
|
||||
static _T &__get_ref(const __OctaFunctorData &__s) {
|
||||
return *__get_ptr_ref(__s);
|
||||
}
|
||||
|
||||
static T *&get_ptr_ref(__OctaFunctorData &s) {
|
||||
return (T *&)s;
|
||||
static _T *&__get_ptr_ref(__OctaFunctorData &__s) {
|
||||
return (_T *&)__s;
|
||||
}
|
||||
|
||||
static T *&get_ptr_ref(const __OctaFunctorData &s) {
|
||||
return (T *&)s;
|
||||
static _T *&__get_ptr_ref(const __OctaFunctorData &__s) {
|
||||
return (_T *&)__s;
|
||||
}
|
||||
};
|
||||
|
||||
struct __OctaFunctionManager;
|
||||
|
||||
struct __OctaFmStorage {
|
||||
__OctaFunctorData data;
|
||||
const __OctaFunctionManager *manager;
|
||||
__OctaFunctorData __data;
|
||||
const __OctaFunctionManager *__manager;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
static const __OctaFunctionManager &__octa_get_default_fm();
|
||||
|
||||
struct __OctaFunctionManager {
|
||||
template<typename T>
|
||||
inline static const __OctaFunctionManager create_default_manager() {
|
||||
template<typename _T>
|
||||
inline static const __OctaFunctionManager __create_default_manager() {
|
||||
return __OctaFunctionManager {
|
||||
&t_call_move_and_destroy<T>,
|
||||
&t_call_copy<T>,
|
||||
&t_call_destroy<T>
|
||||
&__call_move_and_destroy<_T>,
|
||||
&__call_copy<_T>,
|
||||
&__call_destroy<_T>
|
||||
};
|
||||
}
|
||||
|
||||
void (* const call_move_and_destroy)(__OctaFmStorage &lhs,
|
||||
__OctaFmStorage &&rhs);
|
||||
void (* const call_copy)(__OctaFmStorage &lhs,
|
||||
const __OctaFmStorage &rhs);
|
||||
void (* const call_destroy)(__OctaFmStorage &s);
|
||||
void (* const __call_move_and_destroyf)(__OctaFmStorage &__lhs,
|
||||
__OctaFmStorage &&__rhs);
|
||||
void (* const __call_copyf)(__OctaFmStorage &__lhs,
|
||||
const __OctaFmStorage &__rhs);
|
||||
void (* const __call_destroyf)(__OctaFmStorage &__s);
|
||||
|
||||
template<typename T>
|
||||
static void t_call_move_and_destroy(__OctaFmStorage &lhs,
|
||||
__OctaFmStorage &&rhs) {
|
||||
typedef __OctaFunctorDataManager<T> spec;
|
||||
spec::move_f(lhs.data, move(rhs.data));
|
||||
spec::destroy_f(rhs.data);
|
||||
lhs.manager = &__octa_get_default_fm<T>();
|
||||
template<typename _T>
|
||||
static void __call_move_and_destroy(__OctaFmStorage &__lhs,
|
||||
__OctaFmStorage &&__rhs) {
|
||||
typedef __OctaFunctorDataManager<_T> _spec;
|
||||
_spec::__move_f(__lhs.__data, octa::move(__rhs.__data));
|
||||
_spec::__destroy_f(__rhs.__data);
|
||||
__lhs.__manager = &__octa_get_default_fm<_T>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void t_call_copy(__OctaFmStorage &lhs,
|
||||
const __OctaFmStorage &rhs) {
|
||||
typedef __OctaFunctorDataManager<T> spec;
|
||||
lhs.manager = &__octa_get_default_fm<T>();
|
||||
spec::store_f(lhs.data, spec::get_ref(rhs.data));
|
||||
template<typename _T>
|
||||
static void __call_copy(__OctaFmStorage &__lhs,
|
||||
const __OctaFmStorage &__rhs) {
|
||||
typedef __OctaFunctorDataManager<_T> _spec;
|
||||
__lhs.__manager = &__octa_get_default_fm<_T>();
|
||||
_spec::__store_f(__lhs.__data, _spec::__get_ref(__rhs.__data));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void t_call_destroy(__OctaFmStorage &s) {
|
||||
typedef __OctaFunctorDataManager<T> spec;
|
||||
spec::destroy_f(s.data);
|
||||
template<typename _T>
|
||||
static void __call_destroy(__OctaFmStorage &__s) {
|
||||
typedef __OctaFunctorDataManager<_T> _spec;
|
||||
_spec::__destroy_f(__s.__data);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
inline static const __OctaFunctionManager &__octa_get_default_fm() {
|
||||
static const __OctaFunctionManager def_manager
|
||||
= __OctaFunctionManager::create_default_manager<T>();
|
||||
return def_manager;
|
||||
static const __OctaFunctionManager __def_manager
|
||||
= __OctaFunctionManager::__create_default_manager<_T>();
|
||||
return __def_manager;
|
||||
}
|
||||
|
||||
template<typename R, typename...>
|
||||
template<typename _R, typename...>
|
||||
struct __OctaFunction {
|
||||
typedef R ResultType;
|
||||
typedef _R ResultType;
|
||||
};
|
||||
|
||||
template<typename R, typename T>
|
||||
struct __OctaFunction<R, T> {
|
||||
typedef R ResultType;
|
||||
typedef T ArgType;
|
||||
template<typename _R, typename _T>
|
||||
struct __OctaFunction<_R, _T> {
|
||||
typedef _R ResultType;
|
||||
typedef _T ArgType;
|
||||
};
|
||||
|
||||
template<typename R, typename T, typename U>
|
||||
struct __OctaFunction<R, T, U> {
|
||||
typedef R ResultType;
|
||||
typedef T FirstArgType;
|
||||
typedef U SecondArgType;
|
||||
template<typename _R, typename _T, typename _U>
|
||||
struct __OctaFunction<_R, _T, _U> {
|
||||
typedef _R ResultType;
|
||||
typedef _T FirstArgType;
|
||||
typedef _U SecondArgType;
|
||||
};
|
||||
|
||||
template<typename, typename>
|
||||
struct IsValidFunctor {
|
||||
struct __OctaIsValidFunctor {
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template<typename R, typename ...A>
|
||||
struct IsValidFunctor<Function<R(A...)>, R(A...)> {
|
||||
template<typename _R, typename ..._A>
|
||||
struct __OctaIsValidFunctor<Function<_R(_A...)>, _R(_A...)> {
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
struct __OctaEmpty {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T func_to_functor(T &&f) {
|
||||
return forward<T>(f);
|
||||
template<typename _T>
|
||||
_T __octa_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...)) -> decltype(mem_fn(f)) {
|
||||
return mem_fn(f);
|
||||
template<typename _RR, typename _T, typename ..._AA>
|
||||
auto __octa_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) -> decltype(mem_fn(f)) {
|
||||
return mem_fn(f);
|
||||
template<typename _RR, typename _T, typename ..._AA>
|
||||
auto __octa_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(declval<U>())(declval<A>()...)) __octa_test(U *);
|
||||
template<typename _T, typename _R, typename ..._A>
|
||||
struct __OctaIsValidFunctor<_T, _R(_A...)> {
|
||||
template<typename _U>
|
||||
static decltype(__octa_func_to_functor(octa::declval<_U>())
|
||||
(octa::declval<_A>()...)) __test(_U *);
|
||||
template<typename>
|
||||
static __OctaEmpty __octa_test(...);
|
||||
static __OctaEmpty __test(...);
|
||||
|
||||
static constexpr bool value = IsConvertible<
|
||||
decltype(__octa_test<T>(nullptr)), R
|
||||
static constexpr bool value = octa::IsConvertible<
|
||||
decltype(__test<_T>(nullptr)), _R
|
||||
>::value;
|
||||
};
|
||||
|
||||
template<typename R, typename ...A>
|
||||
struct Function<R(A...)>: __OctaFunction<R, A...> {
|
||||
Function( ) { initialize_empty(); }
|
||||
Function(nullptr_t) { initialize_empty(); }
|
||||
template<typename _R, typename ..._A>
|
||||
struct Function<_R(_A...)>: __OctaFunction<_R, _A...> {
|
||||
Function( ) { __init_empty(); }
|
||||
Function(nullptr_t) { __init_empty(); }
|
||||
|
||||
Function(Function &&f) {
|
||||
initialize_empty();
|
||||
swap(f);
|
||||
Function(Function &&__f) {
|
||||
__init_empty();
|
||||
swap(__f);
|
||||
}
|
||||
|
||||
Function(const Function &f): p_call(f.p_call) {
|
||||
f.p_stor.manager->call_copy(p_stor, f.p_stor);
|
||||
Function(const Function &__f): __call(__f.__call) {
|
||||
__f.__stor.__manager->__call_copyf(__stor, __f.__stor);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Function(T f, EnableIf<IsValidFunctor<T, R(A...)>::value, __OctaEmpty>
|
||||
template<typename _T>
|
||||
Function(_T __f, EnableIf<__OctaIsValidFunctor<_T, _R(_A...)>::value, __OctaEmpty>
|
||||
= __OctaEmpty()) {
|
||||
if (func_is_null(f)) {
|
||||
initialize_empty();
|
||||
if (__func_is_null(__f)) {
|
||||
__init_empty();
|
||||
return;
|
||||
}
|
||||
initialize(func_to_functor(forward<T>(f)));
|
||||
__initialize(__octa_func_to_functor(octa::forward<_T>(__f)));
|
||||
}
|
||||
|
||||
~Function() {
|
||||
p_stor.manager->call_destroy(p_stor);
|
||||
__stor.__manager->__call_destroyf(__stor);
|
||||
}
|
||||
|
||||
Function &operator=(Function &&f) {
|
||||
p_stor.manager->call_destroy(p_stor);
|
||||
swap(f);
|
||||
Function &operator=(Function &&__f) {
|
||||
__stor.__manager->__call_destroyf(__stor);
|
||||
swap(__f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Function &operator=(const Function &f) {
|
||||
p_stor.manager->call_destroy(p_stor);
|
||||
f.p_stor.manager->call_copy(p_stor, f.p_stor);
|
||||
Function &operator=(const Function &__f) {
|
||||
__stor.__manager->__call_destroyf(__stor);
|
||||
__f.__stor.__manager->__call_copyf(__stor, __f.__stor);
|
||||
return *this;
|
||||
};
|
||||
|
||||
R operator()(A ...args) const {
|
||||
return p_call(p_stor.data, forward<A>(args)...);
|
||||
_R operator()(_A ...__args) const {
|
||||
return __call(__stor.__data, octa::forward<_A>(__args)...);
|
||||
}
|
||||
|
||||
template<typename F> void assign(F &&f) {
|
||||
Function(forward<F>(f)).swap(*this);
|
||||
template<typename _F> void assign(_F &&__f) {
|
||||
Function(octa::forward<_F>(__f)).swap(*this);
|
||||
}
|
||||
|
||||
void swap(Function &f) {
|
||||
__OctaFmStorage tmp;
|
||||
f.p_stor.manager->call_move_and_destroy(tmp, move(f.p_stor));
|
||||
p_stor.manager->call_move_and_destroy(f.p_stor, move(p_stor));
|
||||
tmp.manager->call_move_and_destroy(p_stor, move(tmp));
|
||||
octa::swap(p_call, f.p_call);
|
||||
void swap(Function &__f) {
|
||||
__OctaFmStorage __tmp;
|
||||
__f.__stor.__manager->__call_move_and_destroyf(__tmp,
|
||||
octa::move(__f.__stor));
|
||||
__stor.__manager->__call_move_and_destroyf(__f.__stor,
|
||||
octa::move(__stor));
|
||||
__tmp.__manager->__call_move_and_destroyf(__stor,
|
||||
octa::move(__tmp));
|
||||
octa::swap(__call, __f.__call);
|
||||
}
|
||||
|
||||
operator bool() const { return p_call != nullptr; }
|
||||
operator bool() const { return __call != nullptr; }
|
||||
|
||||
private:
|
||||
__OctaFmStorage p_stor;
|
||||
R (*p_call)(const __OctaFunctorData &, A...);
|
||||
__OctaFmStorage __stor;
|
||||
_R (*__call)(const __OctaFunctorData &, _A...);
|
||||
|
||||
template<typename T>
|
||||
void initialize(T f) {
|
||||
p_call = &__OctaFunctorDataManager<T>::template call<R, A...>;
|
||||
p_stor.manager = &__octa_get_default_fm<T>();
|
||||
__OctaFunctorDataManager<T>::store_f(p_stor.data, forward<T>(f));
|
||||
template<typename _T>
|
||||
void __initialize(_T __f) {
|
||||
__call = &__OctaFunctorDataManager<_T>::template __call<_R, _A...>;
|
||||
__stor.__manager = &__octa_get_default_fm<_T>();
|
||||
__OctaFunctorDataManager<_T>::__store_f(__stor.__data,
|
||||
octa::forward<_T>(__f));
|
||||
}
|
||||
|
||||
void initialize_empty() {
|
||||
typedef R(*emptyf)(A...);
|
||||
p_call = nullptr;
|
||||
p_stor.manager = &__octa_get_default_fm<emptyf>();
|
||||
__OctaFunctorDataManager<emptyf>::store_f(p_stor.data, nullptr);
|
||||
void __init_empty() {
|
||||
typedef _R(*__emptyf)(_A...);
|
||||
__call = nullptr;
|
||||
__stor.__manager = &__octa_get_default_fm<__emptyf>();
|
||||
__OctaFunctorDataManager<__emptyf>::__store_f(__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...)) {
|
||||
return fptr == nullptr;
|
||||
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...)) {
|
||||
return fptr == nullptr;
|
||||
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) {
|
||||
return fptr == nullptr;
|
||||
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; }
|
||||
}
|
||||
|
||||
#endif
|
|
@ -13,19 +13,19 @@
|
|||
#ifndef OCTA_ALLOW_CXXSTD
|
||||
/* 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;
|
||||
size_t p_len;
|
||||
const _T *__buf;
|
||||
size_t __len;
|
||||
|
||||
initializer_list(const T *v, size_t n): p_buf(v), p_len(n) {}
|
||||
initializer_list(const _T *__v, size_t __n): __buf(__v), __len(__n) {}
|
||||
public:
|
||||
initializer_list(): p_buf(nullptr), p_len(0) {}
|
||||
initializer_list(): __buf(nullptr), __len(0) {}
|
||||
|
||||
size_t size() const { return p_len; }
|
||||
size_t size() const { return __len; }
|
||||
|
||||
const T *begin() const { return p_buf; }
|
||||
const T *end() const { return p_buf + p_len; }
|
||||
const _T *begin() const { return __buf; }
|
||||
const _T *end() const { return __buf + __len; }
|
||||
};
|
||||
}
|
||||
#else
|
||||
|
@ -33,13 +33,11 @@ namespace std {
|
|||
#endif
|
||||
|
||||
namespace octa {
|
||||
using std::initializer_list;
|
||||
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(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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
642
octa/memory.h
642
octa/memory.h
|
@ -15,312 +15,319 @@
|
|||
namespace octa {
|
||||
/* address of */
|
||||
|
||||
template<typename T> constexpr T *address_of(T &v) {
|
||||
return reinterpret_cast<T *>(&const_cast<char &>
|
||||
(reinterpret_cast<const volatile char &>(v)));
|
||||
template<typename _T> constexpr _T *address_of(_T &__v) {
|
||||
return reinterpret_cast<_T *>(&const_cast<char &>
|
||||
(reinterpret_cast<const volatile char &>(__v)));
|
||||
}
|
||||
|
||||
/* pointer traits */
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
struct __OctaHasElementType {
|
||||
template<typename U>
|
||||
static int __octa_test(...);
|
||||
template<typename U>
|
||||
static char __octa_test(typename U::ElementType * = 0);
|
||||
template<typename _U>
|
||||
static int __test(...);
|
||||
template<typename _U>
|
||||
static char __test(typename _U::ElementType * = 0);
|
||||
|
||||
static constexpr bool value = (sizeof(__octa_test<T>(0)) == 1);
|
||||
static constexpr bool value = (sizeof(__test<_T>(0)) == 1);
|
||||
};
|
||||
|
||||
template<typename T, bool = __OctaHasElementType<T>::value>
|
||||
template<typename _T, bool = __OctaHasElementType<_T>::value>
|
||||
struct __OctaPtrTraitsElementType;
|
||||
|
||||
template<typename T> struct __OctaPtrTraitsElementType<T, true> {
|
||||
typedef typename T::ElementType Type;
|
||||
template<typename _T> struct __OctaPtrTraitsElementType<_T, true> {
|
||||
typedef typename _T::ElementType Type;
|
||||
};
|
||||
|
||||
template<template<typename, typename...> class T, typename U, typename ...A>
|
||||
struct __OctaPtrTraitsElementType<T<U, A...>, true> {
|
||||
typedef typename T<U, A...>::ElementType Type;
|
||||
template<template<typename, typename...> class _T, typename _U, typename ..._A>
|
||||
struct __OctaPtrTraitsElementType<_T<_U, _A...>, true> {
|
||||
typedef typename _T<_U, _A...>::ElementType Type;
|
||||
};
|
||||
|
||||
template<template<typename, typename...> class T, typename U, typename ...A>
|
||||
struct __OctaPtrTraitsElementType<T<U, A...>, false> {
|
||||
typedef U Type;
|
||||
template<template<typename, typename...> class _T, typename _U, typename ..._A>
|
||||
struct __OctaPtrTraitsElementType<_T<_U, _A...>, false> {
|
||||
typedef _U Type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
struct __OctaHasDiffType {
|
||||
template<typename U>
|
||||
static int __octa_test(...);
|
||||
template<typename U>
|
||||
static char __octa_test(typename U::DiffType * = 0);
|
||||
template<typename _U>
|
||||
static int __test(...);
|
||||
template<typename _U>
|
||||
static char __test(typename _U::DiffType * = 0);
|
||||
|
||||
static constexpr bool value = (sizeof(__octa_test<T>(0)) == 1);
|
||||
static constexpr bool value = (sizeof(__test<_T>(0)) == 1);
|
||||
};
|
||||
|
||||
template<typename T, bool = __OctaHasDiffType<T>::value>
|
||||
template<typename _T, bool = __OctaHasDiffType<_T>::value>
|
||||
struct __OctaPtrTraitsDiffType {
|
||||
typedef ptrdiff_t Type;
|
||||
};
|
||||
|
||||
template<typename T> struct __OctaPtrTraitsDiffType<T, true> {
|
||||
typedef typename T::DiffType Type;
|
||||
template<typename _T> struct __OctaPtrTraitsDiffType<_T, true> {
|
||||
typedef typename _T::DiffType Type;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
template<typename _T, typename _U>
|
||||
struct __OctaHasRebind {
|
||||
template<typename V>
|
||||
static int __octa_test(...);
|
||||
template<typename V>
|
||||
static char __octa_test(typename V::template rebind<U> * = 0);
|
||||
template<typename _V>
|
||||
static int __test(...);
|
||||
template<typename _V>
|
||||
static char __test(typename _V::template rebind<_U> * = 0);
|
||||
|
||||
static constexpr bool value = (sizeof(__octa_test<T>(0)) == 1);
|
||||
static constexpr bool value = (sizeof(__test<_T>(0)) == 1);
|
||||
};
|
||||
|
||||
template<typename T, typename U, bool = __OctaHasRebind<T, U>::value>
|
||||
template<typename _T, typename _U, bool = __OctaHasRebind<_T, _U>::value>
|
||||
struct __OctaPtrTraitsRebindType {
|
||||
typedef typename T::template rebind<U> Type;
|
||||
typedef typename _T::template rebind<_U> Type;
|
||||
};
|
||||
|
||||
template<template<typename, typename...> class T, typename U,
|
||||
typename ...A, typename V
|
||||
template<template<typename, typename...> class _T, typename _U,
|
||||
typename ..._A, typename _V
|
||||
>
|
||||
struct __OctaPtrTraitsRebindType<T<U, A...>, V, true> {
|
||||
typedef typename T<U, A...>::template rebind<V> Type;
|
||||
struct __OctaPtrTraitsRebindType<_T<_U, _A...>, _V, true> {
|
||||
typedef typename _T<_U, _A...>::template rebind<_V> Type;
|
||||
};
|
||||
|
||||
template<template<typename, typename...> class T, typename U,
|
||||
typename ...A, typename V
|
||||
template<template<typename, typename...> class _T, typename _U,
|
||||
typename ..._A, typename _V
|
||||
>
|
||||
struct __OctaPtrTraitsRebindType<T<U, A...>, V, false> {
|
||||
typedef T<V, A...> Type;
|
||||
struct __OctaPtrTraitsRebindType<_T<_U, _A...>, _V, false> {
|
||||
typedef _T<_V, _A...> Type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
struct __OctaPtrTraitsPointer {
|
||||
typedef T Type;
|
||||
typedef _T Type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct __OctaPtrTraitsPointer<T *> {
|
||||
typedef T *Type;
|
||||
template<typename _T>
|
||||
struct __OctaPtrTraitsPointer<_T *> {
|
||||
typedef _T *Type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using PtrType = typename __OctaPtrTraitsPointer<T>::Type;
|
||||
template<typename _T>
|
||||
using PtrType = typename __OctaPtrTraitsPointer<_T>::Type;
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
struct __OctaPtrTraitsElement {
|
||||
typedef typename __OctaPtrTraitsElementType<T>::Type Type;
|
||||
typedef typename __OctaPtrTraitsElementType<_T>::Type Type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct __OctaPtrTraitsElement<T *> {
|
||||
typedef T Type;
|
||||
template<typename _T>
|
||||
struct __OctaPtrTraitsElement<_T *> {
|
||||
typedef _T Type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using PointerElement = typename __OctaPtrTraitsElement<T>::Type;
|
||||
template<typename _T>
|
||||
using PointerElement = typename __OctaPtrTraitsElement<_T>::Type;
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
struct __OctaPtrTraitsDifference {
|
||||
typedef typename __OctaPtrTraitsDiffType<T>::Type Type;
|
||||
typedef typename __OctaPtrTraitsDiffType<_T>::Type Type;
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct __OctaPtrTraitsDifference<T *> {
|
||||
template<typename _T>
|
||||
struct __OctaPtrTraitsDifference<_T *> {
|
||||
typedef ptrdiff_t DiffType;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using PointerDifference = typename __OctaPtrTraitsDifference<T>::Type;
|
||||
template<typename _T>
|
||||
using PointerDifference = typename __OctaPtrTraitsDifference<_T>::Type;
|
||||
|
||||
template<typename T, typename U>
|
||||
template<typename _T, typename _U>
|
||||
struct __OctaPtrTraitsRebind {
|
||||
using type = typename __OctaPtrTraitsRebindType<T, U>::Type;
|
||||
using type = typename __OctaPtrTraitsRebindType<_T, _U>::Type;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct __OctaPtrTraitsRebind<T *, U> {
|
||||
using type = U *;
|
||||
template<typename _T, typename _U>
|
||||
struct __OctaPtrTraitsRebind<_T *, _U> {
|
||||
using type = _U *;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
using PointerRebind = typename __OctaPtrTraitsRebind<T, U>::Type;
|
||||
template<typename _T, typename _U>
|
||||
using PointerRebind = typename __OctaPtrTraitsRebind<_T, _U>::Type;
|
||||
|
||||
struct __OctaPtrTraitsNat {};
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
struct __OctaPtrTraitsPointerTo {
|
||||
static T pointer_to(Conditional<IsVoid<PointerElement<T>>::value,
|
||||
__OctaPtrTraitsNat, PointerElement<T>
|
||||
> &r) {
|
||||
return T::pointer_to(r);
|
||||
static _T pointer_to(octa::Conditional<
|
||||
octa::IsVoid<PointerElement<_T>>::value,
|
||||
__OctaPtrTraitsNat, PointerElement<_T>
|
||||
> &__r) {
|
||||
return _T::pointer_to(__r);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct __OctaPtrTraitsPointerTo<T *> {
|
||||
static T pointer_to(Conditional<IsVoid<T>::value, __OctaPtrTraitsNat, T
|
||||
> &r) {
|
||||
return octa::address_of(r);
|
||||
template<typename _T>
|
||||
struct __OctaPtrTraitsPointerTo<_T *> {
|
||||
static _T pointer_to(octa::Conditional<
|
||||
octa::IsVoid<_T>::value, __OctaPtrTraitsNat, _T
|
||||
> &__r) {
|
||||
return octa::address_of(__r);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static T pointer_to(Conditional<IsVoid<PointerElement<T>>::value,
|
||||
__OctaPtrTraitsNat, PointerElement<T>
|
||||
> &r) {
|
||||
return __OctaPtrTraitsPointerTo<T>::pointer_to(r);
|
||||
template<typename _T>
|
||||
static _T pointer_to(octa::Conditional<
|
||||
octa::IsVoid<PointerElement<_T>>::value,
|
||||
__OctaPtrTraitsNat, PointerElement<_T>
|
||||
> &__r) {
|
||||
return __OctaPtrTraitsPointerTo<_T>::pointer_to(__r);
|
||||
}
|
||||
|
||||
/* default deleter */
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
struct DefaultDelete {
|
||||
constexpr DefaultDelete() = default;
|
||||
|
||||
template<typename U> DefaultDelete(const DefaultDelete<U> &) {};
|
||||
template<typename _U> DefaultDelete(const DefaultDelete<_U> &) {};
|
||||
|
||||
void operator()(T *p) const {
|
||||
delete p;
|
||||
void operator()(_T *__p) const {
|
||||
delete __p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct DefaultDelete<T[]> {
|
||||
template<typename _T>
|
||||
struct DefaultDelete<_T[]> {
|
||||
constexpr DefaultDelete() = default;
|
||||
|
||||
template<typename U> DefaultDelete(const DefaultDelete<U[]> &) {};
|
||||
template<typename _U> DefaultDelete(const DefaultDelete<_U[]> &) {};
|
||||
|
||||
void operator()(T *p) const {
|
||||
delete[] p;
|
||||
void operator()(_T *__p) const {
|
||||
delete[] __p;
|
||||
}
|
||||
template<typename U> void operator()(U *) const = delete;
|
||||
template<typename _U> void operator()(_U *) const = delete;
|
||||
};
|
||||
|
||||
/* box */
|
||||
|
||||
template<typename T, typename U, bool = IsEmpty<U>::value>
|
||||
template<typename _T, typename _U, bool = octa::IsEmpty<_U>::value>
|
||||
struct __OctaBoxPair;
|
||||
|
||||
template<typename T, typename U>
|
||||
struct __OctaBoxPair<T, U, false> { /* non-empty deleter */
|
||||
T *i_ptr;
|
||||
template<typename _T, typename _U>
|
||||
struct __OctaBoxPair<_T, _U, false> { /* non-empty deleter */
|
||||
_T *__ptr;
|
||||
private:
|
||||
U p_del;
|
||||
_U __del;
|
||||
|
||||
public:
|
||||
template<typename D>
|
||||
__OctaBoxPair(T *ptr, D &&dltr): i_ptr(ptr), p_del(forward<D>(dltr)) {}
|
||||
template<typename _D>
|
||||
__OctaBoxPair(_T *__ptr, _D &&__dltr): __ptr(__ptr),
|
||||
__del(octa::forward<_D>(__dltr)) {}
|
||||
|
||||
U &get_deleter() { return p_del; }
|
||||
const U &get_deleter() const { return p_del; }
|
||||
_U &get_deleter() { return __del; }
|
||||
const _U &get_deleter() const { return __del; }
|
||||
|
||||
void swap(__OctaBoxPair &v) {
|
||||
octa::swap(i_ptr, v.i_ptr);
|
||||
octa::swap(p_del, v.p_del);
|
||||
void swap(__OctaBoxPair &__v) {
|
||||
octa::swap(__ptr, __v.__ptr);
|
||||
octa::swap(__del, __v.__del);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct __OctaBoxPair<T, U, true>: U { /* empty deleter */
|
||||
T *i_ptr;
|
||||
template<typename _T, typename _U>
|
||||
struct __OctaBoxPair<_T, _U, true>: _U { /* empty deleter */
|
||||
_T *__ptr;
|
||||
|
||||
template<typename D>
|
||||
__OctaBoxPair(T *ptr, D &&dltr): U(forward<D>(dltr)), i_ptr(ptr) {}
|
||||
template<typename _D>
|
||||
__OctaBoxPair(_T *__ptr, _D &&__dltr):
|
||||
_U(octa::forward<_D>(__dltr)), __ptr(__ptr) {}
|
||||
|
||||
U &get_deleter() { return *this; }
|
||||
const U &get_deleter() const { return *this; }
|
||||
_U &get_deleter() { return *this; }
|
||||
const _U &get_deleter() const { return *this; }
|
||||
|
||||
void swap(__OctaBoxPair &v) {
|
||||
octa::swap(i_ptr, v.i_ptr);
|
||||
void swap(__OctaBoxPair &__v) {
|
||||
octa::swap(__ptr, __v.__ptr);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
static int __octa_ptr_test(...);
|
||||
template<typename T>
|
||||
static char __octa_ptr_test(typename T::PtrType * = 0);
|
||||
template<typename _T>
|
||||
static char __octa_ptr_test(typename _T::PtrType * = 0);
|
||||
|
||||
template<typename T> struct __OctaHasPtr: IntegralConstant<bool,
|
||||
(sizeof(__octa_ptr_test<T>(0)) == 1)
|
||||
template<typename _T> struct __OctaHasPtr: octa::IntegralConstant<bool,
|
||||
(sizeof(__octa_ptr_test<_T>(0)) == 1)
|
||||
> {};
|
||||
|
||||
template<typename T, typename D, bool = __OctaHasPtr<D>::value>
|
||||
template<typename _T, typename _D, bool = __OctaHasPtr<_D>::value>
|
||||
struct __OctaPtrTypeBase {
|
||||
typedef typename D::PtrType Type;
|
||||
typedef typename _D::PtrType Type;
|
||||
};
|
||||
|
||||
template<typename T, typename D> struct __OctaPtrTypeBase<T, D, false> {
|
||||
typedef T *Type;
|
||||
template<typename _T, typename _D> struct __OctaPtrTypeBase<_T, _D, false> {
|
||||
typedef _T *Type;
|
||||
};
|
||||
|
||||
template<typename T, typename D> struct __OctaPtrType {
|
||||
typedef typename __OctaPtrTypeBase<T, RemoveReference<D>>::Type Type;
|
||||
template<typename _T, typename _D> struct __OctaPtrType {
|
||||
typedef typename __OctaPtrTypeBase<_T, octa::RemoveReference<_D>>::Type Type;
|
||||
};
|
||||
|
||||
template<typename T, typename D = DefaultDelete<T>>
|
||||
template<typename _T, typename _D = DefaultDelete<_T>>
|
||||
struct Box {
|
||||
typedef T ElementType;
|
||||
typedef D DeleterType;
|
||||
typedef typename __OctaPtrType<T, D>::Type PtrType;
|
||||
typedef _T ElementType;
|
||||
typedef _D DeleterType;
|
||||
typedef typename __OctaPtrType<_T, _D>::Type PtrType;
|
||||
|
||||
private:
|
||||
struct __OctaNat { int x; };
|
||||
struct __OctaNat { int __x; };
|
||||
|
||||
typedef RemoveReference<D> &D_ref;
|
||||
typedef const RemoveReference<D> &D_cref;
|
||||
typedef RemoveReference<_D> &_D_ref;
|
||||
typedef const RemoveReference<_D> &_D_cref;
|
||||
|
||||
public:
|
||||
constexpr Box(): p_stor(nullptr, D()) {
|
||||
static_assert(!IsPointer<D>::value,
|
||||
constexpr Box(): __stor(nullptr, _D()) {
|
||||
static_assert(!octa::IsPointer<_D>::value,
|
||||
"Box constructed with null fptr deleter");
|
||||
}
|
||||
constexpr Box(nullptr_t): p_stor(nullptr, D()) {
|
||||
static_assert(!IsPointer<D>::value,
|
||||
constexpr Box(nullptr_t): __stor(nullptr, _D()) {
|
||||
static_assert(!octa::IsPointer<_D>::value,
|
||||
"Box constructed with null fptr deleter");
|
||||
}
|
||||
|
||||
explicit Box(PtrType p): p_stor(p, D()) {
|
||||
static_assert(!IsPointer<D>::value,
|
||||
explicit Box(PtrType __p): __stor(__p, _D()) {
|
||||
static_assert(!octa::IsPointer<_D>::value,
|
||||
"Box constructed with null fptr deleter");
|
||||
}
|
||||
|
||||
Box(PtrType p, Conditional<IsReference<D>::value,
|
||||
D, AddLvalueReference<const D>
|
||||
> d): p_stor(p, d) {}
|
||||
Box(PtrType __p, octa::Conditional<octa::IsReference<_D>::value,
|
||||
_D, octa::AddLvalueReference<const _D>
|
||||
> __d): __stor(__p, __d) {}
|
||||
|
||||
Box(PtrType p, RemoveReference<D> &&d): p_stor(p, move(d)) {
|
||||
static_assert(!IsReference<D>::value,
|
||||
Box(PtrType __p, octa::RemoveReference<_D> &&__d):
|
||||
__stor(__p, octa::move(__d)) {
|
||||
static_assert(!octa::IsReference<_D>::value,
|
||||
"rvalue deleter cannot be a ref");
|
||||
}
|
||||
|
||||
Box(Box &&u): p_stor(u.release(), forward<D>(u.get_deleter())) {}
|
||||
Box(Box &&__u): __stor(__u.release(),
|
||||
octa::forward<_D>(__u.get_deleter())) {}
|
||||
|
||||
template<typename TT, typename DD>
|
||||
Box(Box<TT, DD> &&u, EnableIf<!IsArray<TT>::value
|
||||
&& IsConvertible<typename Box<TT, DD>::PtrType, PtrType>::value
|
||||
&& IsConvertible<DD, D>::value
|
||||
&& (!IsReference<D>::value || IsSame<D, DD>::value)
|
||||
> = __OctaNat()): p_stor(u.release(), forward<DD>(u.get_deleter())) {}
|
||||
template<typename _TT, typename _DD>
|
||||
Box(Box<_TT, _DD> &&__u, octa::EnableIf<!octa::IsArray<_TT>::value
|
||||
&& octa::IsConvertible<typename Box<_TT, _DD>::PtrType, PtrType>::value
|
||||
&& octa::IsConvertible<_DD, _D>::value
|
||||
&& (!octa::IsReference<_D>::value || octa::IsSame<_D, _DD>::value)
|
||||
> = __OctaNat()): __stor(__u.release(), octa::forward<_DD>(__u.get_deleter())) {}
|
||||
|
||||
Box &operator=(Box &&u) {
|
||||
reset(u.release());
|
||||
p_stor.get_deleter() = forward<D>(u.get_deleter());
|
||||
Box &operator=(Box &&__u) {
|
||||
reset(__u.release());
|
||||
__stor.get_deleter() = octa::forward<_D>(__u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename TT, typename DD>
|
||||
EnableIf<!IsArray<TT>::value
|
||||
&& IsConvertible<typename Box<TT, DD>::PtrType, PtrType>::value
|
||||
&& IsAssignable<D &, DD &&>::value,
|
||||
template<typename _TT, typename _DD>
|
||||
EnableIf<!octa::IsArray<_TT>::value
|
||||
&& octa::IsConvertible<typename Box<_TT, _DD>::PtrType, PtrType>::value
|
||||
&& octa::IsAssignable<_D &, _DD &&>::value,
|
||||
Box &
|
||||
> operator=(Box<TT, DD> &&u) {
|
||||
reset(u.release());
|
||||
p_stor.get_deleter() = forward<DD>(u.get_deleter());
|
||||
> operator=(Box<_TT, _DD> &&__u) {
|
||||
reset(__u.release());
|
||||
__stor.get_deleter() = octa::forward<_DD>(__u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -331,128 +338,133 @@ namespace octa {
|
|||
|
||||
~Box() { reset(); }
|
||||
|
||||
AddLvalueReference<T> operator*() const { return *p_stor.i_ptr; }
|
||||
PtrType operator->() const { return p_stor.i_ptr; }
|
||||
octa::AddLvalueReference<_T> operator*() const { return *__stor.__ptr; }
|
||||
PtrType operator->() const { return __stor.__ptr; }
|
||||
|
||||
explicit operator bool() const {
|
||||
return p_stor.i_ptr != nullptr;
|
||||
return __stor.__ptr != nullptr;
|
||||
}
|
||||
|
||||
PtrType get() const { return p_stor.i_ptr; }
|
||||
PtrType get() const { return __stor.__ptr; }
|
||||
|
||||
D_ref get_deleter() { return p_stor.get_deleter(); }
|
||||
D_cref get_deleter() const { return p_stor.get_deleter(); }
|
||||
_D_ref get_deleter() { return __stor.get_deleter(); }
|
||||
_D_cref get_deleter() const { return __stor.get_deleter(); }
|
||||
|
||||
PtrType release() {
|
||||
PtrType p = p_stor.i_ptr;
|
||||
p_stor.i_ptr = nullptr;
|
||||
return p;
|
||||
PtrType __p = __stor.__ptr;
|
||||
__stor.__ptr = nullptr;
|
||||
return __p;
|
||||
}
|
||||
|
||||
void reset(PtrType p = nullptr) {
|
||||
PtrType tmp = p_stor.i_ptr;
|
||||
p_stor.i_ptr = p;
|
||||
if (tmp) p_stor.get_deleter()(tmp);
|
||||
void reset(PtrType __p = nullptr) {
|
||||
PtrType __tmp = __stor.__ptr;
|
||||
__stor.__ptr = __p;
|
||||
if (__tmp) __stor.get_deleter()(__tmp);
|
||||
}
|
||||
|
||||
void swap(Box &u) {
|
||||
p_stor.swap(u.p_stor);
|
||||
void swap(Box &__u) {
|
||||
__stor.swap(__u.__stor);
|
||||
}
|
||||
|
||||
private:
|
||||
__OctaBoxPair<T, D> p_stor;
|
||||
__OctaBoxPair<_T, _D> __stor;
|
||||
};
|
||||
|
||||
template<typename T, typename U, bool = IsSame<
|
||||
RemoveCv<PointerElement<T>>,
|
||||
RemoveCv<PointerElement<U>>
|
||||
>::value> struct __OctaSameOrLessCvQualifiedBase: IsConvertible<T, U> {};
|
||||
template<typename _T, typename _U, bool = octa::IsSame<
|
||||
octa::RemoveCv<PointerElement<_T>>,
|
||||
octa::RemoveCv<PointerElement<_U>>
|
||||
>::value> struct __OctaSameOrLessCvQualifiedBase: octa::IsConvertible<_T, _U> {};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct __OctaSameOrLessCvQualifiedBase<T, U, false>: False {};
|
||||
template<typename _T, typename _U>
|
||||
struct __OctaSameOrLessCvQualifiedBase<_T, _U, false>: octa::False {};
|
||||
|
||||
template<typename T, typename U, bool = IsPointer<T>::value
|
||||
|| IsSame<T, U>::value || __OctaHasElementType<T>::value
|
||||
> struct __OctaSameOrLessCvQualified: __OctaSameOrLessCvQualifiedBase<T, U> {};
|
||||
template<typename _T, typename _U, bool = octa::IsPointer<_T>::value
|
||||
|| octa::IsSame<_T, _U>::value || __OctaHasElementType<_T>::value
|
||||
> struct __OctaSameOrLessCvQualified: __OctaSameOrLessCvQualifiedBase<_T, _U> {};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct __OctaSameOrLessCvQualified<T, U, false>: False {};
|
||||
template<typename _T, typename _U>
|
||||
struct __OctaSameOrLessCvQualified<_T, _U, false>: octa::False {};
|
||||
|
||||
template<typename T, typename D>
|
||||
struct Box<T[], D> {
|
||||
typedef T ElementType;
|
||||
typedef D DeleterType;
|
||||
typedef typename __OctaPtrType<T, D>::Type PtrType;
|
||||
template<typename _T, typename _D>
|
||||
struct Box<_T[], _D> {
|
||||
typedef _T ElementType;
|
||||
typedef _D DeleterType;
|
||||
typedef typename __OctaPtrType<_T, _D>::Type PtrType;
|
||||
|
||||
private:
|
||||
struct __OctaNat { int x; };
|
||||
struct __OctaNat { int __x; };
|
||||
|
||||
typedef RemoveReference<D> &D_ref;
|
||||
typedef const RemoveReference<D> &D_cref;
|
||||
typedef RemoveReference<_D> &_D_ref;
|
||||
typedef const RemoveReference<_D> &_D_cref;
|
||||
|
||||
public:
|
||||
constexpr Box(): p_stor(nullptr, D()) {
|
||||
static_assert(!IsPointer<D>::value,
|
||||
constexpr Box(): __stor(nullptr, _D()) {
|
||||
static_assert(!octa::IsPointer<_D>::value,
|
||||
"Box constructed with null fptr deleter");
|
||||
}
|
||||
constexpr Box(nullptr_t): p_stor(nullptr, D()) {
|
||||
static_assert(!IsPointer<D>::value,
|
||||
constexpr Box(nullptr_t): __stor(nullptr, _D()) {
|
||||
static_assert(!octa::IsPointer<_D>::value,
|
||||
"Box constructed with null fptr deleter");
|
||||
}
|
||||
|
||||
template<typename U> explicit Box(U p, EnableIf<
|
||||
__OctaSameOrLessCvQualified<U, PtrType>::value, __OctaNat
|
||||
> = __OctaNat()): p_stor(p, D()) {
|
||||
static_assert(!IsPointer<D>::value,
|
||||
template<typename _U> explicit Box(_U __p, octa::EnableIf<
|
||||
__OctaSameOrLessCvQualified<_U, PtrType>::value, __OctaNat
|
||||
> = __OctaNat()): __stor(__p, _D()) {
|
||||
static_assert(!octa::IsPointer<_D>::value,
|
||||
"Box constructed with null fptr deleter");
|
||||
}
|
||||
|
||||
template<typename U> Box(U p, Conditional<IsReference<D>::value,
|
||||
D, AddLvalueReference<const D>
|
||||
> d, EnableIf<__OctaSameOrLessCvQualified<U, PtrType>::value, __OctaNat
|
||||
> = __OctaNat()): p_stor(p, d) {}
|
||||
template<typename _U> Box(_U __p, octa::Conditional<
|
||||
octa::IsReference<_D>::value,
|
||||
_D, AddLvalueReference<const _D>
|
||||
> __d, octa::EnableIf<__OctaSameOrLessCvQualified<_U, PtrType>::value,
|
||||
__OctaNat> = __OctaNat()): __stor(__p, __d) {}
|
||||
|
||||
Box(nullptr_t, Conditional<IsReference<D>::value,
|
||||
D, AddLvalueReference<const D>
|
||||
> d): p_stor(nullptr, d) {}
|
||||
Box(nullptr_t, octa::Conditional<octa::IsReference<_D>::value,
|
||||
_D, AddLvalueReference<const _D>
|
||||
> __d): __stor(nullptr, __d) {}
|
||||
|
||||
template<typename U> Box(U p, RemoveReference<D> &&d, EnableIf<
|
||||
__OctaSameOrLessCvQualified<U, PtrType>::value, __OctaNat
|
||||
> = __OctaNat()): p_stor(p, move(d)) {
|
||||
static_assert(!IsReference<D>::value,
|
||||
template<typename _U> Box(_U __p, octa::RemoveReference<_D> &&__d,
|
||||
octa::EnableIf<
|
||||
__OctaSameOrLessCvQualified<_U, PtrType>::value, __OctaNat
|
||||
> = __OctaNat()): __stor(__p, octa::move(__d)) {
|
||||
static_assert(!octa::IsReference<_D>::value,
|
||||
"rvalue deleter cannot be a ref");
|
||||
}
|
||||
|
||||
Box(nullptr_t, RemoveReference<D> &&d): p_stor(nullptr, move(d)) {
|
||||
static_assert(!IsReference<D>::value,
|
||||
Box(nullptr_t, octa::RemoveReference<_D> &&__d):
|
||||
__stor(nullptr, octa::move(__d)) {
|
||||
static_assert(!octa::IsReference<_D>::value,
|
||||
"rvalue deleter cannot be a ref");
|
||||
}
|
||||
|
||||
Box(Box &&u): p_stor(u.release(), forward<D>(u.get_deleter())) {}
|
||||
Box(Box &&__u): __stor(__u.release(),
|
||||
octa::forward<_D>(__u.get_deleter())) {}
|
||||
|
||||
template<typename TT, typename DD>
|
||||
Box(Box<TT, DD> &&u, EnableIf<IsArray<TT>::value
|
||||
&& __OctaSameOrLessCvQualified<typename Box<TT, DD>::PtrType,
|
||||
template<typename _TT, typename _DD>
|
||||
Box(Box<_TT, _DD> &&__u, EnableIf<IsArray<_TT>::value
|
||||
&& __OctaSameOrLessCvQualified<typename Box<_TT, _DD>::PtrType,
|
||||
PtrType>::value
|
||||
&& IsConvertible<DD, D>::value
|
||||
&& (!IsReference<D>::value || IsSame<D, DD>::value)> = __OctaNat()
|
||||
): p_stor(u.release(), forward<DD>(u.get_deleter())) {}
|
||||
&& octa::IsConvertible<_DD, _D>::value
|
||||
&& (!octa::IsReference<_D>::value ||
|
||||
octa::IsSame<_D, _DD>::value)> = __OctaNat()
|
||||
): __stor(__u.release(), octa::forward<_DD>(__u.get_deleter())) {}
|
||||
|
||||
Box &operator=(Box &&u) {
|
||||
reset(u.release());
|
||||
p_stor.get_deleter() = forward<D>(u.get_deleter());
|
||||
Box &operator=(Box &&__u) {
|
||||
reset(__u.release());
|
||||
__stor.get_deleter() = octa::forward<_D>(__u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename TT, typename DD>
|
||||
EnableIf<IsArray<TT>::value
|
||||
&& __OctaSameOrLessCvQualified<typename Box<TT, DD>::PtrType,
|
||||
template<typename _TT, typename _DD>
|
||||
EnableIf<octa::IsArray<_TT>::value
|
||||
&& __OctaSameOrLessCvQualified<typename Box<_TT, _DD>::PtrType,
|
||||
PtrType>::value
|
||||
&& IsAssignable<D &, DD &&>::value,
|
||||
&& IsAssignable<_D &, _DD &&>::value,
|
||||
Box &
|
||||
> operator=(Box<TT, DD> &&u) {
|
||||
reset(u.release());
|
||||
p_stor.get_deleter() = forward<DD>(u.get_deleter());
|
||||
> operator=(Box<_TT, _DD> &&__u) {
|
||||
reset(__u.release());
|
||||
__stor.get_deleter() = octa::forward<_DD>(__u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -463,75 +475,75 @@ namespace octa {
|
|||
|
||||
~Box() { reset(); }
|
||||
|
||||
AddLvalueReference<T> operator[](size_t idx) const {
|
||||
return p_stor.i_ptr[idx];
|
||||
octa::AddLvalueReference<_T> operator[](size_t __idx) const {
|
||||
return __stor.__ptr[__idx];
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return p_stor.i_ptr != nullptr;
|
||||
return __stor.__ptr != nullptr;
|
||||
}
|
||||
|
||||
PtrType get() const { return p_stor.i_ptr; }
|
||||
PtrType get() const { return __stor.__ptr; }
|
||||
|
||||
D_ref get_deleter() { return p_stor.get_deleter(); }
|
||||
D_cref get_deleter() const { return p_stor.get_deleter(); }
|
||||
_D_ref get_deleter() { return __stor.get_deleter(); }
|
||||
_D_cref get_deleter() const { return __stor.get_deleter(); }
|
||||
|
||||
PtrType release() {
|
||||
PtrType p = p_stor.i_ptr;
|
||||
p_stor.i_ptr = nullptr;
|
||||
return p;
|
||||
PtrType __p = __stor.__ptr;
|
||||
__stor.__ptr = nullptr;
|
||||
return __p;
|
||||
}
|
||||
|
||||
template<typename U> EnableIf<
|
||||
__OctaSameOrLessCvQualified<U, PtrType>::value, void
|
||||
> reset(U p) {
|
||||
PtrType tmp = p_stor.i_ptr;
|
||||
p_stor.i_ptr = p;
|
||||
if (tmp) p_stor.get_deleter()(tmp);
|
||||
template<typename _U> EnableIf<
|
||||
__OctaSameOrLessCvQualified<_U, PtrType>::value, void
|
||||
> reset(_U __p) {
|
||||
PtrType __tmp = __stor.__ptr;
|
||||
__stor.__ptr = __p;
|
||||
if (__tmp) __stor.get_deleter()(__tmp);
|
||||
}
|
||||
|
||||
void reset(nullptr_t) {
|
||||
PtrType tmp = p_stor.i_ptr;
|
||||
p_stor.i_ptr = nullptr;
|
||||
if (tmp) p_stor.get_deleter()(tmp);
|
||||
PtrType __tmp = __stor.__ptr;
|
||||
__stor.__ptr = nullptr;
|
||||
if (__tmp) __stor.get_deleter()(__tmp);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
reset(nullptr);
|
||||
}
|
||||
|
||||
void swap(Box &u) {
|
||||
p_stor.swap(u.p_stor);
|
||||
void swap(Box &__u) {
|
||||
__stor.swap(__u.__stor);
|
||||
}
|
||||
|
||||
private:
|
||||
__OctaBoxPair<T, D> p_stor;
|
||||
__OctaBoxPair<_T, _D> __stor;
|
||||
};
|
||||
|
||||
template<typename T> struct __OctaBoxIf {
|
||||
typedef Box<T> __OctaBox;
|
||||
template<typename _T> struct __OctaBoxIf {
|
||||
typedef Box<_T> __OctaBox;
|
||||
};
|
||||
|
||||
template<typename T> struct __OctaBoxIf<T[]> {
|
||||
typedef Box<T[]> __OctaBoxUnknownSize;
|
||||
template<typename _T> struct __OctaBoxIf<_T[]> {
|
||||
typedef Box<_T[]> __OctaBoxUnknownSize;
|
||||
};
|
||||
|
||||
template<typename T, size_t N> struct __OctaBoxIf<T[N]> {
|
||||
template<typename _T, size_t _N> struct __OctaBoxIf<_T[_N]> {
|
||||
typedef void __OctaBoxKnownSize;
|
||||
};
|
||||
|
||||
template<typename T, typename ...A>
|
||||
typename __OctaBoxIf<T>::__OctaBox make_box(A &&...args) {
|
||||
return Box<T>(new T(forward<A>(args)...));
|
||||
template<typename _T, typename ..._A>
|
||||
typename __OctaBoxIf<_T>::__OctaBox make_box(_A &&...__args) {
|
||||
return Box<_T>(new _T(octa::forward<_A>(__args)...));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename __OctaBoxIf<T>::__OctaBoxUnknownSize make_box(size_t n) {
|
||||
return Box<T>(new RemoveExtent<T>[n]());
|
||||
template<typename _T>
|
||||
typename __OctaBoxIf<_T>::__OctaBoxUnknownSize make_box(size_t __n) {
|
||||
return Box<_T>(new octa::RemoveExtent<_T>[__n]());
|
||||
}
|
||||
|
||||
template<typename T, typename ...A>
|
||||
typename __OctaBoxIf<T>::__OctaBoxKnownSize make_box(A &&...args) = delete;
|
||||
template<typename _T, typename ..._A>
|
||||
typename __OctaBoxIf<_T>::__OctaBoxKnownSize make_box(_A &&...__args) = delete;
|
||||
|
||||
/* allocator */
|
||||
|
||||
|
@ -542,7 +554,7 @@ namespace octa {
|
|||
typedef void *PtrType;
|
||||
typedef const void *ConstPtrType;
|
||||
|
||||
template<typename U> using Rebind = Allocator<U>;
|
||||
template<typename _U> using Rebind = Allocator<_U>;
|
||||
};
|
||||
|
||||
template<> struct Allocator<const void> {
|
||||
|
@ -550,81 +562,81 @@ namespace octa {
|
|||
typedef const void *PtrType;
|
||||
typedef const void *ConstPtrType;
|
||||
|
||||
template<typename U> using Rebind = Allocator<U>;
|
||||
template<typename _U> using Rebind = Allocator<_U>;
|
||||
};
|
||||
|
||||
template<typename T> struct Allocator {
|
||||
typedef size_t SizeType;
|
||||
typedef ptrdiff_t DiffType;
|
||||
typedef T ValType;
|
||||
typedef T &RefType;
|
||||
typedef const T &ConstRefType;
|
||||
typedef T *PtrType;
|
||||
typedef const T *ConstPtrType;
|
||||
template<typename _T> struct Allocator {
|
||||
typedef size_t SizeType;
|
||||
typedef ptrdiff_t DiffType;
|
||||
typedef _T ValType;
|
||||
typedef _T &RefType;
|
||||
typedef const _T &ConstRefType;
|
||||
typedef _T *PtrType;
|
||||
typedef const _T *ConstPtrType;
|
||||
|
||||
template<typename U> using Rebind = Allocator<U>;
|
||||
template<typename _U> using Rebind = Allocator<_U>;
|
||||
|
||||
PtrType address(RefType v) const {
|
||||
return address_of(v);
|
||||
PtrType address(RefType __v) const {
|
||||
return address_of(__v);
|
||||
};
|
||||
ConstPtrType address(ConstRefType v) const {
|
||||
return address_of(v);
|
||||
ConstPtrType address(ConstRefType __v) const {
|
||||
return address_of(__v);
|
||||
};
|
||||
|
||||
SizeType max_size() const { return SizeType(~0) / sizeof(T); }
|
||||
SizeType max_size() const { return SizeType(~0) / sizeof(_T); }
|
||||
|
||||
PtrType allocate(SizeType n, Allocator<void>::ConstPtrType = nullptr) {
|
||||
return (PtrType) ::new uchar[n * sizeof(T)];
|
||||
PtrType allocate(SizeType __n, Allocator<void>::ConstPtrType = nullptr) {
|
||||
return (PtrType) ::new uchar[__n * sizeof(_T)];
|
||||
}
|
||||
|
||||
void deallocate(PtrType p, SizeType) { ::delete[] (uchar *) p; }
|
||||
void deallocate(PtrType __p, SizeType) { ::delete[] (uchar *) __p; }
|
||||
|
||||
template<typename U, typename ...A>
|
||||
void construct(U *p, A &&...args) {
|
||||
::new((void *)p) U(forward<A>(args)...);
|
||||
template<typename _U, typename ..._A>
|
||||
void construct(_U *__p, _A &&...__args) {
|
||||
::new((void *)__p) _U(octa::forward<_A>(__args)...);
|
||||
}
|
||||
|
||||
void destroy(PtrType p) { p->~T(); }
|
||||
void destroy(PtrType __p) { __p->~_T(); }
|
||||
};
|
||||
|
||||
template<typename T> struct Allocator<const T> {
|
||||
typedef size_t SizeType;
|
||||
typedef ptrdiff_t DiffType;
|
||||
typedef const T ValType;
|
||||
typedef const T &RefType;
|
||||
typedef const T &ConstRefType;
|
||||
typedef const T *PtrType;
|
||||
typedef const T *ConstPtrType;
|
||||
template<typename _T> struct Allocator<const _T> {
|
||||
typedef size_t SizeType;
|
||||
typedef ptrdiff_t DiffType;
|
||||
typedef const _T ValType;
|
||||
typedef const _T &RefType;
|
||||
typedef const _T &ConstRefType;
|
||||
typedef const _T *PtrType;
|
||||
typedef const _T *ConstPtrType;
|
||||
|
||||
template<typename U> using Rebind = Allocator<U>;
|
||||
template<typename _U> using Rebind = Allocator<_U>;
|
||||
|
||||
ConstPtrType address(ConstRefType v) const {
|
||||
return address_of(v);
|
||||
ConstPtrType address(ConstRefType __v) const {
|
||||
return address_of(__v);
|
||||
};
|
||||
|
||||
SizeType max_size() const { return SizeType(~0) / sizeof(T); }
|
||||
SizeType max_size() const { return SizeType(~0) / sizeof(_T); }
|
||||
|
||||
PtrType allocate(SizeType n, Allocator<void>::ConstPtrType = nullptr) {
|
||||
return (PtrType) ::new uchar[n * sizeof(T)];
|
||||
PtrType allocate(SizeType __n, Allocator<void>::ConstPtrType = nullptr) {
|
||||
return (PtrType) ::new uchar[__n * sizeof(_T)];
|
||||
}
|
||||
|
||||
void deallocate(PtrType p, SizeType) { ::delete[] (uchar *) p; }
|
||||
void deallocate(PtrType __p, SizeType) { ::delete[] (uchar *) __p; }
|
||||
|
||||
template<typename U, typename ...A>
|
||||
void construct(U *p, A &&...args) {
|
||||
::new((void *)p) U(forward<A>(args)...);
|
||||
template<typename _U, typename ..._A>
|
||||
void construct(_U *__p, _A &&...__args) {
|
||||
::new((void *)__p) _U(octa::forward<_A>(__args)...);
|
||||
}
|
||||
|
||||
void destroy(PtrType p) { p->~T(); }
|
||||
void destroy(PtrType __p) { __p->~_T(); }
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
bool operator==(const Allocator<T> &, const Allocator<U> &) {
|
||||
template<typename _T, typename _U>
|
||||
bool operator==(const Allocator<_T> &, const Allocator<_U> &) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
bool operator!=(const Allocator<T> &, const Allocator<U> &) {
|
||||
template<typename _T, typename _U>
|
||||
bool operator!=(const Allocator<_T> &, const Allocator<_U> &) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
1012
octa/range.h
1012
octa/range.h
File diff suppressed because it is too large
Load diff
387
octa/string.h
387
octa/string.h
|
@ -14,298 +14,298 @@
|
|||
#include "octa/vector.h"
|
||||
|
||||
namespace octa {
|
||||
using std::initializer_list;
|
||||
|
||||
static constexpr size_t npos = -1;
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
class StringBase {
|
||||
Vector<T> p_buf;
|
||||
octa::Vector<_T> __buf;
|
||||
|
||||
void terminate() {
|
||||
if (p_buf.empty() || (p_buf.back() != '\0')) p_buf.push('\0');
|
||||
void __terminate() {
|
||||
if (__buf.empty() || (__buf.back() != '\0')) __buf.push('\0');
|
||||
}
|
||||
|
||||
public:
|
||||
typedef size_t SizeType;
|
||||
typedef ptrdiff_t DiffType;
|
||||
typedef T ValType;
|
||||
typedef T &RefType;
|
||||
typedef const T &ConstRefType;
|
||||
typedef T *PtrType;
|
||||
typedef const T *ConstPtrType;
|
||||
typedef PointerRange< T> RangeType;
|
||||
typedef PointerRange<const T> ConstRangeType;
|
||||
typedef size_t SizeType;
|
||||
typedef ptrdiff_t DiffType;
|
||||
typedef _T ValType;
|
||||
typedef _T &RefType;
|
||||
typedef const _T &ConstRefType;
|
||||
typedef _T *PtrType;
|
||||
typedef const _T *ConstPtrType;
|
||||
typedef PointerRange< _T> RangeType;
|
||||
typedef PointerRange<const _T> ConstRangeType;
|
||||
|
||||
StringBase(): p_buf(1, '\0') {}
|
||||
StringBase(): __buf(1, '\0') {}
|
||||
|
||||
StringBase(const StringBase &s): p_buf(s.p_buf) {}
|
||||
StringBase(StringBase &&s): p_buf(move(s.p_buf)) {}
|
||||
StringBase(const StringBase &__s): __buf(__s.__buf) {}
|
||||
StringBase(StringBase &&__s): __buf(octa::move(__s.__buf)) {}
|
||||
|
||||
StringBase(const StringBase &s, size_t pos, size_t len = npos):
|
||||
p_buf(s.p_buf.each().slice(pos,
|
||||
(len == npos) ? s.p_buf.size() : (pos + len))) {
|
||||
terminate();
|
||||
StringBase(const StringBase &__s, size_t __pos, size_t __len = npos):
|
||||
__buf(__s.__buf.each().slice(__pos,
|
||||
(__len == npos) ? __s.__buf.size() : (__pos + __len))) {
|
||||
__terminate();
|
||||
}
|
||||
|
||||
/* TODO: traits for utf-16/utf-32 string lengths, for now assume char */
|
||||
StringBase(const T *v): p_buf(PointerRange<const T>(v, strlen(v) + 1)) {}
|
||||
StringBase(const _T *__v): __buf(ConstRangeType(__v, strlen(__v) + 1)) {}
|
||||
|
||||
template<typename R> StringBase(R range): p_buf(range) {
|
||||
terminate();
|
||||
template<typename _R> StringBase(_R __range): __buf(__range) {
|
||||
__terminate();
|
||||
}
|
||||
|
||||
void clear() { p_buf.clear(); }
|
||||
void clear() { __buf.clear(); }
|
||||
|
||||
StringBase<T> &operator=(const StringBase &v) {
|
||||
p_buf.operator=(v);
|
||||
StringBase<_T> &operator=(const StringBase &__v) {
|
||||
__buf.operator=(__v);
|
||||
return *this;
|
||||
}
|
||||
StringBase<T> &operator=(StringBase &&v) {
|
||||
p_buf.operator=(move(v));
|
||||
StringBase<_T> &operator=(StringBase &&__v) {
|
||||
__buf.operator=(octa::move(__v));
|
||||
return *this;
|
||||
}
|
||||
StringBase<T> &operator=(const T *v) {
|
||||
p_buf = PointerRange<const T>(v, strlen(v) + 1);
|
||||
StringBase<_T> &operator=(const _T *__v) {
|
||||
__buf = ConstRangeType(__v, strlen(__v) + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void resize(size_t n, T v = T()) {
|
||||
p_buf.pop();
|
||||
p_buf.resize(n, v);
|
||||
terminate();
|
||||
void resize(size_t __n, _T __v = _T()) {
|
||||
__buf.pop();
|
||||
__buf.resize(__n, __v);
|
||||
__terminate();
|
||||
}
|
||||
|
||||
void reserve(size_t n) {
|
||||
p_buf.reserve(n + 1);
|
||||
void reserve(size_t __n) {
|
||||
__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 __buf[__i]; }
|
||||
const _T &operator[](size_t __i) const { return __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 __buf[__i]; }
|
||||
const _T &at(size_t __i) const { return __buf[__i]; }
|
||||
|
||||
T &front() { return p_buf[0]; }
|
||||
const T &front() const { return p_buf[0]; };
|
||||
_T &front() { return __buf[0]; }
|
||||
const _T &front() const { return __buf[0]; };
|
||||
|
||||
T &back() { return p_buf[size() - 1]; }
|
||||
const T &back() const { return p_buf[size() - 1]; }
|
||||
_T &back() { return __buf[size() - 1]; }
|
||||
const _T &back() const { return __buf[size() - 1]; }
|
||||
|
||||
T *data() { return p_buf.data(); }
|
||||
const T *data() const { return p_buf.data(); }
|
||||
_T *data() { return __buf.data(); }
|
||||
const _T *data() const { return __buf.data(); }
|
||||
|
||||
size_t size() const {
|
||||
return p_buf.size() - 1;
|
||||
return __buf.size() - 1;
|
||||
}
|
||||
|
||||
size_t capacity() const {
|
||||
return p_buf.capacity() - 1;
|
||||
return __buf.capacity() - 1;
|
||||
}
|
||||
|
||||
bool empty() const { return (size() == 0); }
|
||||
|
||||
void push(T v) {
|
||||
p_buf.back() = v;
|
||||
p_buf.push('\0');
|
||||
void push(_T __v) {
|
||||
__buf.back() = __v;
|
||||
__buf.push('\0');
|
||||
}
|
||||
|
||||
StringBase<T> &append(const StringBase &s) {
|
||||
p_buf.pop();
|
||||
p_buf.insert_range(p_buf.size(), s.p_buf.each());
|
||||
StringBase<_T> &append(const StringBase &__s) {
|
||||
__buf.pop();
|
||||
__buf.insert_range(__buf.size(), __s.__buf.each());
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBase<T> &append(const StringBase &s, size_t idx, size_t len) {
|
||||
p_buf.pop();
|
||||
p_buf.insert_range(p_buf.size(), PointerRange<T>(&s[idx],
|
||||
(len == npos) ? (s.size() - idx) : len));
|
||||
terminate();
|
||||
StringBase<_T> &append(const StringBase &__s, size_t __idx, size_t __len) {
|
||||
__buf.pop();
|
||||
__buf.insert_range(__buf.size(), octa::PointerRange<_T>(&__s[__idx],
|
||||
(__len == npos) ? (__s.size() - __idx) : __len));
|
||||
__terminate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBase<T> &append(const T *s) {
|
||||
p_buf.pop();
|
||||
p_buf.insert_range(p_buf.size(), PointerRange<const T>(s,
|
||||
strlen(s) + 1));
|
||||
StringBase<_T> &append(const _T *__s) {
|
||||
__buf.pop();
|
||||
__buf.insert_range(__buf.size(), ConstRangeType(__s,
|
||||
strlen(__s) + 1));
|
||||
return *this;
|
||||
}
|
||||
|
||||
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');
|
||||
StringBase<_T> &append(size_t __n, _T __c) {
|
||||
__buf.pop();
|
||||
for (size_t __i = 0; __i < __n; ++__i) __buf.push(__c);
|
||||
__buf.push('\0');
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
StringBase<T> &append_range(R range) {
|
||||
p_buf.pop();
|
||||
p_buf.insert_range(p_buf.size(), range);
|
||||
terminate();
|
||||
template<typename _R>
|
||||
StringBase<_T> &append_range(_R __range) {
|
||||
__buf.pop();
|
||||
__buf.insert_range(__buf.size(), __range);
|
||||
__terminate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBase<T> &operator+=(const StringBase &s) {
|
||||
return append(s);
|
||||
StringBase<_T> &operator+=(const StringBase &__s) {
|
||||
return append(__s);
|
||||
}
|
||||
StringBase<T> &operator+=(const T *s) {
|
||||
return append(s);
|
||||
StringBase<_T> &operator+=(const _T *__s) {
|
||||
return append(__s);
|
||||
}
|
||||
StringBase<T> &operator+=(T c) {
|
||||
p_buf.pop();
|
||||
p_buf.push(c);
|
||||
p_buf.push('\0');
|
||||
StringBase<_T> &operator+=(_T __c) {
|
||||
__buf.pop();
|
||||
__buf.push(__c);
|
||||
__buf.push('\0');
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangeType each() {
|
||||
return PointerRange<T>(p_buf.data(), size());
|
||||
return RangeType(__buf.data(), size());
|
||||
}
|
||||
ConstRangeType each() const {
|
||||
return PointerRange<const T>(p_buf.data(), size());
|
||||
return ConstRangeType(__buf.data(), size());
|
||||
}
|
||||
|
||||
void swap(StringBase &v) {
|
||||
p_buf.swap(v);
|
||||
void swap(StringBase &__v) {
|
||||
__buf.swap(__v);
|
||||
}
|
||||
};
|
||||
|
||||
typedef StringBase<char> String;
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
struct __OctaIsRangeTest {
|
||||
template<typename U> static char __octa_test(typename U::Category *);
|
||||
template<typename U> static int __octa_test(...);
|
||||
static constexpr bool value = (sizeof(__octa_test<T>(0)) == sizeof(char));
|
||||
template<typename _U> static char __test(typename _U::Category *);
|
||||
template<typename _U> static int __test(...);
|
||||
static constexpr bool value = (sizeof(__test<_T>(0)) == sizeof(char));
|
||||
};
|
||||
|
||||
template<typename T, typename F>
|
||||
String concat(const T &v, const String &sep, F func) {
|
||||
String ret;
|
||||
auto range = each(v);
|
||||
if (range.empty()) return move(ret);
|
||||
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);
|
||||
for (;;) {
|
||||
ret += func(range.front());
|
||||
range.pop_front();
|
||||
if (range.empty()) break;
|
||||
ret += sep;
|
||||
__ret += __func(__range.front());
|
||||
__range.pop_front();
|
||||
if (__range.empty()) break;
|
||||
__ret += __sep;
|
||||
}
|
||||
return move(ret);
|
||||
return octa::move(__ret);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
String concat(const T &v, const String &sep = " ") {
|
||||
String ret;
|
||||
auto range = each(v);
|
||||
if (range.empty()) return move(ret);
|
||||
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);
|
||||
for (;;) {
|
||||
ret += range.front();
|
||||
range.pop_front();
|
||||
if (range.empty()) break;
|
||||
ret += sep;
|
||||
__ret += __range.front();
|
||||
__range.pop_front();
|
||||
if (__range.empty()) break;
|
||||
__ret += __sep;
|
||||
}
|
||||
return move(ret);
|
||||
return octa::move(__ret);
|
||||
}
|
||||
|
||||
template<typename T, typename F>
|
||||
String concat(initializer_list<T> v, const String &sep, F func) {
|
||||
return concat(each(v), sep, 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(initializer_list<T> v, const String &sep = " ") {
|
||||
return concat(each(v), sep);
|
||||
template<typename _T>
|
||||
String concat(std::initializer_list<_T> __v, const String &__sep = " ") {
|
||||
return concat(octa::each(__v), __sep);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
struct __OctaToStringTest {
|
||||
template<typename U, String (U::*)() const> struct __OctaTest {};
|
||||
template<typename U> static char __octa_test(__OctaTest<U, &U::to_string> *);
|
||||
template<typename U> static int __octa_test(...);
|
||||
static constexpr bool value = (sizeof(__octa_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 ArgType;
|
||||
template<typename _T> struct ToString {
|
||||
typedef _T ArgType;
|
||||
typedef String ResultType;
|
||||
|
||||
template<typename U>
|
||||
static String __octa_to_str(const U &v,
|
||||
EnableIf<__OctaToStringTest<U>::value, bool> = true
|
||||
template<typename _U>
|
||||
static String __octa_to_str(const _U &__v,
|
||||
octa::EnableIf<__OctaToStringTest<_U>::value, bool> = true
|
||||
) {
|
||||
return v.to_string();
|
||||
return __v.to_string();
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
static String __octa_to_str(const U &v,
|
||||
EnableIf<!__OctaToStringTest<U>::value && !IsScalar<U>::value,
|
||||
bool> = true
|
||||
template<typename _U>
|
||||
static String __octa_to_str(const _U &__v,
|
||||
octa::EnableIf<!__OctaToStringTest<_U>::value &&
|
||||
!octa::IsScalar<_U>::value, bool> = true
|
||||
) {
|
||||
String ret("{");
|
||||
ret += concat(each(v), ", ", ToString<RangeReference<
|
||||
decltype(each(v))
|
||||
String __ret("{");
|
||||
__ret += concat(octa::each(__v), ", ", ToString<octa::RangeReference<
|
||||
decltype(octa::each(__v))
|
||||
>>());
|
||||
ret += "}";
|
||||
return move(ret);
|
||||
__ret += "}";
|
||||
return octa::move(__ret);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
static String __octa_to_str(const U &v,
|
||||
EnableIf<!__OctaToStringTest<U>::value && IsScalar<U>::value,
|
||||
bool> = true
|
||||
template<typename _U>
|
||||
static String __octa_to_str(const _U &__v,
|
||||
octa::EnableIf<!__OctaToStringTest<_U>::value &&
|
||||
octa::IsScalar<_U>::value, bool> = true
|
||||
) {
|
||||
return ToString<U>()(v);
|
||||
return ToString<_U>()(__v);
|
||||
}
|
||||
|
||||
String operator()(const T &v) {
|
||||
return move(__octa_to_str<RemoveCv<RemoveReference<T>>>(v));
|
||||
String operator()(const _T &__v) {
|
||||
return octa::move(__octa_to_str<octa::RemoveCv<
|
||||
octa::RemoveReference<_T>
|
||||
>>(__v));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void __octa_str_printf(Vector<char> *s, const char *fmt, T v) {
|
||||
char buf[256];
|
||||
int n = snprintf(buf, sizeof(buf), fmt, v);
|
||||
s->clear();
|
||||
s->reserve(n + 1);
|
||||
if (n >= (int)sizeof(buf))
|
||||
snprintf(s->data(), n + 1, fmt, v);
|
||||
else if (n > 0)
|
||||
memcpy(s->data(), buf, n + 1);
|
||||
template<typename _T>
|
||||
void __octa_str_printf(octa::Vector<char> *__s, const char *__fmt, _T __v) {
|
||||
char __buf[256];
|
||||
int __n = snprintf(__buf, sizeof(__buf), __fmt, __v);
|
||||
__s->clear();
|
||||
__s->reserve(__n + 1);
|
||||
if (__n >= (int)sizeof(__buf))
|
||||
snprintf(__s->data(), __n + 1, __fmt, __v);
|
||||
else if (__n > 0)
|
||||
memcpy(__s->data(), __buf, __n + 1);
|
||||
else {
|
||||
n = 0;
|
||||
*(s->data()) = '\0';
|
||||
__n = 0;
|
||||
*(__s->data()) = '\0';
|
||||
}
|
||||
*(((size_t *)s) + 1) = n + 1;
|
||||
*(((size_t *)__s) + 1) = __n + 1;
|
||||
}
|
||||
|
||||
template<> struct ToString<bool> {
|
||||
typedef bool ArgType;
|
||||
typedef String ResultType;
|
||||
String operator()(bool b) {
|
||||
return b ? "true" : "false";
|
||||
String operator()(bool __b) {
|
||||
return __b ? "true" : "false";
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct ToString<char> {
|
||||
typedef char ArgType;
|
||||
typedef String ResultType;
|
||||
String operator()(char c) {
|
||||
String ret;
|
||||
ret.push(c);
|
||||
return move(ret);
|
||||
String operator()(char __c) {
|
||||
String __ret;
|
||||
__ret.push(__c);
|
||||
return octa::move(__ret);
|
||||
}
|
||||
};
|
||||
|
||||
#define __OCTA_TOSTR_NUM(T, fmt) \
|
||||
template<> struct ToString<T> { \
|
||||
typedef T ArgType; \
|
||||
#define __OCTA_TOSTR_NUM(_T, __fmt) \
|
||||
template<> struct ToString<_T> { \
|
||||
typedef _T ArgType; \
|
||||
typedef String ResultType; \
|
||||
String operator()(T v) { \
|
||||
String ret; \
|
||||
__octa_str_printf((Vector<char> *)&ret, fmt, v); \
|
||||
return move(ret); \
|
||||
String operator()(_T __v) { \
|
||||
String __ret; \
|
||||
__octa_str_printf((octa::Vector<char> *)&__ret, __fmt, __v); \
|
||||
return octa::move(__ret); \
|
||||
} \
|
||||
};
|
||||
|
||||
|
@ -322,45 +322,48 @@ namespace octa {
|
|||
|
||||
#undef __OCTA_TOSTR_NUM
|
||||
|
||||
template<typename T> struct ToString<T *> {
|
||||
typedef T *ArgType;
|
||||
template<typename _T> struct ToString<_T *> {
|
||||
typedef _T *ArgType;
|
||||
typedef String ResultType;
|
||||
String operator()(ArgType v) {
|
||||
String ret;
|
||||
__octa_str_printf((Vector<char> *)&ret, "%p", v);
|
||||
return move(ret);
|
||||
String operator()(ArgType __v) {
|
||||
String __ret;
|
||||
__octa_str_printf((octa::Vector<char> *)&__ret, "%p", __v);
|
||||
return octa::move(__ret);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct ToString<String> {
|
||||
typedef const String &ArgType;
|
||||
typedef String ResultType;
|
||||
String operator()(ArgType s) {
|
||||
return s;
|
||||
String operator()(ArgType __s) {
|
||||
return __s;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U> struct ToString<Pair<T, U>> {
|
||||
typedef const Pair<T, U> &ArgType;
|
||||
template<typename _T, typename _U> struct ToString<octa::Pair<_T, _U>> {
|
||||
typedef const octa::Pair<_T, _U> &ArgType;
|
||||
typedef String ResultType;
|
||||
String operator()(ArgType v) {
|
||||
String ret("{");
|
||||
ret += ToString<RemoveCv<RemoveReference<T>>>()(v.first);
|
||||
ret += ", ";
|
||||
ret += ToString<RemoveCv<RemoveReference<U>>>()(v.second);
|
||||
ret += "}";
|
||||
return move(ret);
|
||||
String operator()(ArgType __v) {
|
||||
String __ret("{");
|
||||
__ret += ToString<octa::RemoveCv<octa::RemoveReference<_T>>>()
|
||||
(__v.first);
|
||||
__ret += ", ";
|
||||
__ret += ToString<octa::RemoveCv<octa::RemoveReference<_U>>>()
|
||||
(__v.second);
|
||||
__ret += "}";
|
||||
return octa::move(__ret);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
String to_string(const T &v) {
|
||||
return move(ToString<RemoveCv<RemoveReference<T>>>()(v));
|
||||
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(initializer_list<T> init) {
|
||||
return move(ToString<initializer_list<T>>()(init));
|
||||
template<typename _T>
|
||||
String to_string(std::initializer_list<_T> __init) {
|
||||
return octa::move(ToString<std::initializer_list<_T>>()(__init));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
112
octa/utility.h
112
octa/utility.h
|
@ -13,67 +13,67 @@
|
|||
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);
|
||||
}
|
||||
|
||||
/* declval */
|
||||
|
||||
template<typename T> AddRvalueReference<T> declval();
|
||||
template<typename _T> AddRvalueReference<_T> declval();
|
||||
|
||||
/* swap */
|
||||
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
struct __OctaSwapTest {
|
||||
template<typename U, void (U::*)(U &)> struct __OctaTest {};
|
||||
template<typename U> static char __octa_test(__OctaTest<U, &U::swap> *);
|
||||
template<typename U> static int __octa_test(...);
|
||||
static constexpr bool value = (sizeof(__octa_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 __octa_swap(T &a, T &b, EnableIf<
|
||||
__OctaSwapTest<T>::value, bool
|
||||
template<typename _T> inline void __octa_swap(_T &__a, _T &__b, EnableIf<
|
||||
__OctaSwapTest<_T>::value, bool
|
||||
> = true) {
|
||||
a.swap(b);
|
||||
__a.swap(__b);
|
||||
}
|
||||
|
||||
template<typename T> inline void __octa_swap(T &a, T &b, EnableIf<
|
||||
!__OctaSwapTest<T>::value, bool
|
||||
template<typename _T> inline void __octa_swap(_T &__a, _T &__b, EnableIf<
|
||||
!__OctaSwapTest<_T>::value, bool
|
||||
> = true) {
|
||||
T c(move(a));
|
||||
a = move(b);
|
||||
b = move(c);
|
||||
_T __c(octa::move(__a));
|
||||
__a = octa::move(__b);
|
||||
__b = octa::move(__c);
|
||||
}
|
||||
|
||||
template<typename T> void swap(T &a, T &b) {
|
||||
__octa_swap(a, b);
|
||||
template<typename _T> void swap(_T &__a, _T &__b) {
|
||||
__octa_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) {
|
||||
swap(a[i], b[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;
|
||||
|
@ -81,46 +81,48 @@ namespace octa {
|
|||
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(forward<TT>(x)), second(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): first(move(v.first)), second(move(v.second)) {}
|
||||
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) {
|
||||
first = v.first;
|
||||
second = v.second;
|
||||
Pair &operator=(const Pair &__v) {
|
||||
first = __v.first;
|
||||
second = __v.second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename TT, typename UU>
|
||||
Pair &operator=(const Pair<TT, UU> &v) {
|
||||
first = v.first;
|
||||
second = v.second;
|
||||
template<typename _TT, typename _UU>
|
||||
Pair &operator=(const Pair<_TT, _UU> &__v) {
|
||||
first = __v.first;
|
||||
second = __v.second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Pair &operator=(Pair &&v) {
|
||||
first = move(v.first);
|
||||
second = move(v.second);
|
||||
Pair &operator=(Pair &&__v) {
|
||||
first = octa::move(__v.first);
|
||||
second = octa::move(__v.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename TT, typename UU>
|
||||
Pair &operator=(Pair<TT, UU> &&v) {
|
||||
first = forward<TT>(v.first);
|
||||
second = 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;
|
||||
}
|
||||
|
||||
void swap(Pair &v) {
|
||||
octa::swap(first, v.first);
|
||||
octa::swap(second, v.second);
|
||||
void swap(Pair &__v) {
|
||||
octa::swap(first, __v.first);
|
||||
octa::swap(second, __v.second);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
365
octa/vector.h
365
octa/vector.h
|
@ -17,298 +17,297 @@
|
|||
#include "octa/initializer_list.h"
|
||||
|
||||
namespace octa {
|
||||
template<typename T>
|
||||
template<typename _T>
|
||||
class Vector {
|
||||
T *p_buf;
|
||||
size_t p_len, p_cap;
|
||||
_T *__buf;
|
||||
size_t __len, __cap;
|
||||
|
||||
void insert_base(size_t idx, size_t n) {
|
||||
if (p_len + n > p_cap) reserve(p_len + n);
|
||||
p_len += n;
|
||||
for (size_t i = p_len - 1; i > idx + n - 1; --i) {
|
||||
p_buf[i] = move(p_buf[i - n]);
|
||||
void __insert_base(size_t __idx, size_t __n) {
|
||||
if (__len + __n > __cap) reserve(__len + __n);
|
||||
__len += __n;
|
||||
for (size_t __i = __len - 1; __i > __idx + __n - 1; --__i) {
|
||||
__buf[__i] = octa::move(__buf[__i - __n]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
void ctor_from_range(R &range, EnableIf<IsFiniteRandomAccessRange<R>
|
||||
::value, bool
|
||||
template<typename _R>
|
||||
void __ctor_from_range(_R &__range, octa::EnableIf<
|
||||
octa::IsFiniteRandomAccessRange<_R>::value, bool
|
||||
> = true) {
|
||||
RangeSize<R> len = range.size();
|
||||
reserve(len);
|
||||
p_len = len;
|
||||
for (size_t i = 0; !range.empty(); range.pop_front()) {
|
||||
new (&p_buf[i]) T(range.front());
|
||||
++i;
|
||||
octa::RangeSize<_R> __l = __range.size();
|
||||
reserve(__l);
|
||||
__len = __l;
|
||||
for (size_t __i = 0; !__range.empty(); __range.pop_front()) {
|
||||
new (&__buf[__i]) _T(__range.front());
|
||||
++__i;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
void ctor_from_range(R &range, EnableIf<!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()) {
|
||||
reserve(i + 1);
|
||||
new (&p_buf[i]) T(range.front());
|
||||
++i;
|
||||
p_len = i;
|
||||
size_t __i = 0;
|
||||
for (; !__range.empty(); __range.pop_front()) {
|
||||
reserve(__i + 1);
|
||||
new (&__buf[__i]) _T(__range.front());
|
||||
++__i;
|
||||
__len = __i;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
enum { MIN_SIZE = 8 };
|
||||
|
||||
typedef size_t SizeType;
|
||||
typedef ptrdiff_t DiffType;
|
||||
typedef T ValType;
|
||||
typedef T &RefType;
|
||||
typedef const T &ConstRefType;
|
||||
typedef T *PtrType;
|
||||
typedef const T *ConstPtrType;
|
||||
typedef PointerRange< T> RangeType;
|
||||
typedef PointerRange<const T> ConstRangeType;
|
||||
typedef size_t SizeType;
|
||||
typedef ptrdiff_t DiffType;
|
||||
typedef _T ValType;
|
||||
typedef _T &RefType;
|
||||
typedef const _T &ConstRefType;
|
||||
typedef _T *PtrType;
|
||||
typedef const _T *ConstPtrType;
|
||||
typedef PointerRange< _T> RangeType;
|
||||
typedef PointerRange<const _T> ConstRangeType;
|
||||
|
||||
Vector(): p_buf(nullptr), p_len(0), p_cap(0) {}
|
||||
Vector(): __buf(nullptr), __len(0), __cap(0) {}
|
||||
|
||||
explicit Vector(size_t n, const T &val = T()): Vector() {
|
||||
p_buf = (T *)new uchar[n * sizeof(T)];
|
||||
p_len = p_cap = n;
|
||||
T *cur = p_buf, *last = p_buf + n;
|
||||
while (cur != last) new (cur++) T(val);
|
||||
explicit Vector(size_t __n, const _T &__val = _T()): Vector() {
|
||||
__buf = (_T *)new uchar[__n * sizeof(_T)];
|
||||
__len = __cap = __n;
|
||||
_T *__cur = __buf, *__last = __buf + __n;
|
||||
while (__cur != __last) new (__cur++) _T(__val);
|
||||
}
|
||||
|
||||
Vector(const Vector &v): Vector() {
|
||||
*this = v;
|
||||
Vector(const Vector &__v): Vector() {
|
||||
*this = __v;
|
||||
}
|
||||
|
||||
Vector(Vector &&v): p_buf(v.p_buf), p_len(v.p_len), p_cap(v.p_cap) {
|
||||
v.p_buf = nullptr;
|
||||
v.p_len = v.p_cap = 0;
|
||||
Vector(Vector &&__v): __buf(__v.__buf), __len(__v.__len),
|
||||
__cap(__v.__cap) {
|
||||
__v.__buf = nullptr;
|
||||
__v.__len = __v.__cap = 0;
|
||||
}
|
||||
|
||||
Vector(InitializerList<T> v): Vector() {
|
||||
size_t len = v.end() - v.begin();
|
||||
const T *ptr = v.begin();
|
||||
reserve(len);
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
new (&p_buf[i]) T(ptr[i]);
|
||||
p_len = len;
|
||||
Vector(InitializerList<_T> __v): Vector() {
|
||||
size_t __l = __v.end() - __v.begin();
|
||||
const _T *__ptr = __v.begin();
|
||||
reserve(__l);
|
||||
for (size_t __i = 0; __i < __l; ++__i)
|
||||
new (&__buf[__i]) _T(__ptr[__i]);
|
||||
__len = __l;
|
||||
}
|
||||
|
||||
template<typename R> Vector(R range): Vector() {
|
||||
ctor_from_range(range);
|
||||
template<typename _R> Vector(_R __range): Vector() {
|
||||
__ctor_from_range(__range);
|
||||
}
|
||||
|
||||
~Vector() {
|
||||
clear();
|
||||
delete[] (uchar *)p_buf;
|
||||
p_buf = nullptr;
|
||||
p_cap = 0;
|
||||
delete[] (uchar *)__buf;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if (p_len > 0 && !octa::IsPod<T>()) {
|
||||
T *cur = p_buf, *last = p_buf + p_len;
|
||||
while (cur != last) (*cur++).~T();
|
||||
if (__len > 0 && !octa::IsPod<_T>()) {
|
||||
_T *__cur = __buf, *__last = __buf + __len;
|
||||
while (__cur != __last) (*__cur++).~_T();
|
||||
}
|
||||
p_len = 0;
|
||||
__len = 0;
|
||||
}
|
||||
|
||||
Vector<T> &operator=(const Vector<T> &v) {
|
||||
if (this == &v) return *this;
|
||||
Vector<_T> &operator=(const Vector<_T> &__v) {
|
||||
if (this == &__v) return *this;
|
||||
clear();
|
||||
reserve(v.p_cap);
|
||||
p_len = v.p_len;
|
||||
if (octa::IsPod<T>()) {
|
||||
memcpy(p_buf, v.p_buf, p_len * sizeof(T));
|
||||
reserve(__v.__cap);
|
||||
__len = __v.__len;
|
||||
if (octa::IsPod<_T>()) {
|
||||
memcpy(__buf, __v.__buf, __len * sizeof(_T));
|
||||
} else {
|
||||
T *cur = p_buf, *last = p_buf + p_len;
|
||||
T *vbuf = v.p_buf;
|
||||
while (cur != last) {
|
||||
new (cur++) T(*vbuf++);
|
||||
_T *__cur = __buf, *__last = __buf + __len;
|
||||
_T *__vbuf = __v.__buf;
|
||||
while (__cur != __last) {
|
||||
new (__cur++) _T(*__vbuf++);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector<T> &operator=(Vector<T> &&v) {
|
||||
Vector<_T> &operator=(Vector<_T> &&__v) {
|
||||
clear();
|
||||
delete[] (uchar *)p_buf;
|
||||
p_len = v.p_len;
|
||||
p_cap = v.p_cap;
|
||||
p_buf = v.disown();
|
||||
delete[] (uchar *)__buf;
|
||||
__len = __v.__len;
|
||||
__cap = __v.__cap;
|
||||
__buf = __v.disown();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector<T> &operator=(InitializerList<T> il) {
|
||||
Vector<_T> &operator=(InitializerList<_T> __il) {
|
||||
clear();
|
||||
size_t ilen = il.end() - il.begin();
|
||||
reserve(ilen);
|
||||
if (octa::IsPod<T>()) {
|
||||
memcpy(p_buf, il.begin(), ilen);
|
||||
size_t __ilen = __il.end() - __il.begin();
|
||||
reserve(__ilen);
|
||||
if (octa::IsPod<_T>()) {
|
||||
memcpy(__buf, __il.begin(), __ilen);
|
||||
} else {
|
||||
T *buf = p_buf, *ibuf = il.begin(), *last = il.end();
|
||||
while (ibuf != last) {
|
||||
new (buf++) T(*ibuf++);
|
||||
_T *__tbuf = __buf, *__ibuf = __il.begin(), *__last = __il.end();
|
||||
while (__ibuf != __last) {
|
||||
new (__tbuf++) _T(*__ibuf++);
|
||||
}
|
||||
}
|
||||
p_len = ilen;
|
||||
__len = __ilen;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
Vector<T> &operator=(R range) {
|
||||
template<typename _R>
|
||||
Vector<_T> &operator=(_R __range) {
|
||||
clear();
|
||||
ctor_from_range(range);
|
||||
__ctor_from_range(__range);
|
||||
}
|
||||
|
||||
void resize(size_t n, const T &v = T()) {
|
||||
size_t len = p_len;
|
||||
reserve(n);
|
||||
p_len = n;
|
||||
if (octa::IsPod<T>()) {
|
||||
for (size_t i = len; i < p_len; ++i) {
|
||||
p_buf[i] = T(v);
|
||||
void resize(size_t __n, const _T &__v = _T()) {
|
||||
size_t __l = __len;
|
||||
reserve(__n);
|
||||
__len = __n;
|
||||
if (octa::IsPod<_T>()) {
|
||||
for (size_t __i = __l; __i < __len; ++__i) {
|
||||
__buf[__i] = _T(__v);
|
||||
}
|
||||
} else {
|
||||
T *first = p_buf + len;
|
||||
T *last = p_buf + p_len;
|
||||
while (first != last) new (first++) T(v);
|
||||
_T *__first = __buf + __l;
|
||||
_T *__last = __buf + __len;
|
||||
while (__first != __last) new (__first++) _T(__v);
|
||||
}
|
||||
}
|
||||
|
||||
void reserve(size_t n) {
|
||||
if (n <= p_cap) return;
|
||||
size_t oc = p_cap;
|
||||
if (!oc) {
|
||||
p_cap = max(n, size_t(MIN_SIZE));
|
||||
void reserve(size_t __n) {
|
||||
if (__n <= __cap) return;
|
||||
size_t __oc = __cap;
|
||||
if (!__oc) {
|
||||
__cap = octa::max(__n, size_t(MIN_SIZE));
|
||||
} else {
|
||||
while (p_cap < n) p_cap *= 2;
|
||||
while (__cap < __n) __cap *= 2;
|
||||
}
|
||||
T *tmp = (T *)new uchar[p_cap * sizeof(T)];
|
||||
if (oc > 0) {
|
||||
if (octa::IsPod<T>()) {
|
||||
memcpy(tmp, p_buf, p_len * sizeof(T));
|
||||
_T *__tmp = (_T *)new uchar[__cap * sizeof(_T)];
|
||||
if (__oc > 0) {
|
||||
if (octa::IsPod<_T>()) {
|
||||
memcpy(__tmp, __buf, __len * sizeof(_T));
|
||||
} else {
|
||||
T *cur = p_buf, *tcur = tmp, *last = tmp + p_len;
|
||||
while (tcur != last) {
|
||||
new (tcur++) T(move(*cur));
|
||||
(*cur).~T();
|
||||
++cur;
|
||||
_T *__cur = __buf, *__tcur = __tmp, *__last = __tmp + __len;
|
||||
while (__tcur != __last) {
|
||||
new (__tcur++) _T(octa::move(*__cur));
|
||||
(*__cur).~_T();
|
||||
++__cur;
|
||||
}
|
||||
}
|
||||
delete[] (uchar *)p_buf;
|
||||
delete[] (uchar *)__buf;
|
||||
}
|
||||
p_buf = tmp;
|
||||
__buf = __tmp;
|
||||
}
|
||||
|
||||
T &operator[](size_t i) { return p_buf[i]; }
|
||||
const T &operator[](size_t i) const { return p_buf[i]; }
|
||||
_T &operator[](size_t __i) { return __buf[__i]; }
|
||||
const _T &operator[](size_t __i) const { return __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 __buf[__i]; }
|
||||
const _T &at(size_t __i) const { return __buf[__i]; }
|
||||
|
||||
T &push(const T &v) {
|
||||
if (p_len == p_cap) reserve(p_len + 1);
|
||||
new (&p_buf[p_len]) T(v);
|
||||
return p_buf[p_len++];
|
||||
_T &push(const _T &__v) {
|
||||
if (__len == __cap) reserve(__len + 1);
|
||||
new (&__buf[__len]) _T(__v);
|
||||
return __buf[__len++];
|
||||
}
|
||||
|
||||
T &push() {
|
||||
if (p_len == p_cap) reserve(p_len + 1);
|
||||
new (&p_buf[p_len]) T;
|
||||
return p_buf[p_len++];
|
||||
_T &push() {
|
||||
if (__len == __cap) reserve(__len + 1);
|
||||
new (&__buf[__len]) _T;
|
||||
return __buf[__len++];
|
||||
}
|
||||
|
||||
template<typename ...U>
|
||||
T &emplace_back(U &&...args) {
|
||||
if (p_len == p_cap) reserve(p_len + 1);
|
||||
new (&p_buf[p_len]) T(forward<U>(args)...);
|
||||
return p_buf[p_len++];
|
||||
template<typename ..._U>
|
||||
_T &emplace_back(_U &&...__args) {
|
||||
if (__len == __cap) reserve(__len + 1);
|
||||
new (&__buf[__len]) _T(octa::forward<_U>(__args)...);
|
||||
return __buf[__len++];
|
||||
}
|
||||
|
||||
void pop() {
|
||||
if (!octa::IsPod<T>()) {
|
||||
p_buf[--p_len].~T();
|
||||
if (!octa::IsPod<_T>()) {
|
||||
__buf[--__len].~_T();
|
||||
} else {
|
||||
--p_len;
|
||||
--__len;
|
||||
}
|
||||
}
|
||||
|
||||
T &front() { return p_buf[0]; }
|
||||
const T &front() const { return p_buf[0]; };
|
||||
_T &front() { return __buf[0]; }
|
||||
const _T &front() const { return __buf[0]; };
|
||||
|
||||
T &back() { return p_buf[p_len - 1]; }
|
||||
const T &back() const { return p_buf[p_len - 1]; }
|
||||
_T &back() { return __buf[__len - 1]; }
|
||||
const _T &back() const { return __buf[__len - 1]; }
|
||||
|
||||
T *data() { return p_buf; }
|
||||
const T *data() const { return p_buf; }
|
||||
_T *data() { return __buf; }
|
||||
const _T *data() const { return __buf; }
|
||||
|
||||
size_t size() const { return p_len; }
|
||||
size_t capacity() const { return p_cap; }
|
||||
size_t size() const { return __len; }
|
||||
size_t capacity() const { return __cap; }
|
||||
|
||||
bool empty() const { return (p_len == 0); }
|
||||
bool empty() const { return (__len == 0); }
|
||||
|
||||
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) {
|
||||
return ptr >= p_buf && ptr < &p_buf[p_len];
|
||||
bool in_range(size_t __idx) { return __idx < __len; }
|
||||
bool in_range(int __idx) { return __idx >= 0 && size_t(__idx) < __len; }
|
||||
bool in_range(const _T *__ptr) {
|
||||
return __ptr >= __buf && __ptr < &__buf[__len];
|
||||
}
|
||||
|
||||
T *disown() {
|
||||
T *r = p_buf;
|
||||
p_buf = nullptr;
|
||||
p_len = p_cap = 0;
|
||||
return r;
|
||||
_T *disown() {
|
||||
_T *__r = __buf;
|
||||
__buf = nullptr;
|
||||
__len = __cap = 0;
|
||||
return __r;
|
||||
}
|
||||
|
||||
T *insert(size_t idx, T &&v) {
|
||||
insert_base(idx, 1);
|
||||
p_buf[idx] = move(v);
|
||||
return &p_buf[idx];
|
||||
_T *insert(size_t __idx, _T &&__v) {
|
||||
__insert_base(__idx, 1);
|
||||
__buf[__idx] = octa::move(__v);
|
||||
return &__buf[__idx];
|
||||
}
|
||||
|
||||
T *insert(size_t idx, const T &v) {
|
||||
insert_base(idx, 1);
|
||||
p_buf[idx] = v;
|
||||
return &p_buf[idx];
|
||||
_T *insert(size_t __idx, const _T &__v) {
|
||||
__insert_base(__idx, 1);
|
||||
__buf[__idx] = __v;
|
||||
return &__buf[__idx];
|
||||
}
|
||||
|
||||
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[idx + i] = v;
|
||||
_T *insert(size_t __idx, size_t __n, const _T &__v) {
|
||||
__insert_base(__idx, __n);
|
||||
for (size_t __i = 0; __i < __n; ++__i) {
|
||||
__buf[__idx + __i] = __v;
|
||||
}
|
||||
return &p_buf[idx];
|
||||
return &__buf[__idx];
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
T *insert_range(size_t idx, U range) {
|
||||
size_t len = range.size();
|
||||
insert_base(idx, len);
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
p_buf[idx + i] = range.front();
|
||||
range.pop_front();
|
||||
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) {
|
||||
__buf[__idx + __i] = __range.front();
|
||||
__range.pop_front();
|
||||
}
|
||||
return &p_buf[idx];
|
||||
return &__buf[__idx];
|
||||
}
|
||||
|
||||
T *insert(size_t idx, InitializerList<T> il) {
|
||||
return insert_range(idx, octa::each(il));
|
||||
_T *insert(size_t __idx, InitializerList<_T> __il) {
|
||||
return insert_range(__idx, octa::each(__il));
|
||||
}
|
||||
|
||||
RangeType each() {
|
||||
return PointerRange<T>(p_buf, p_buf + p_len);
|
||||
return RangeType(__buf, __buf + __len);
|
||||
}
|
||||
ConstRangeType each() const {
|
||||
return PointerRange<const T>(p_buf, p_buf + p_len);
|
||||
return ConstRangeType(__buf, __buf + __len);
|
||||
}
|
||||
|
||||
void swap(Vector &v) {
|
||||
octa::swap(p_len, v.p_len);
|
||||
octa::swap(p_cap, v.p_cap);
|
||||
octa::swap(p_buf, v.p_buf);
|
||||
void swap(Vector &__v) {
|
||||
octa::swap(__len, __v.__len);
|
||||
octa::swap(__cap, __v.__cap);
|
||||
octa::swap(__buf, __v.__buf);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue