deuglify template args

master
Daniel Kolesa 2015-06-04 22:57:06 +01:00
parent 47016ec6ad
commit 84d78ba87a
11 changed files with 2179 additions and 2179 deletions

View File

@ -17,9 +17,9 @@ namespace octa {
/* partitioning */
template<typename _R, typename _U>
_R partition(_R range, _U pred) {
_R ret = range;
template<typename R, typename U>
R partition(R range, U pred) {
R ret = range;
for (; !range.empty(); range.pop_front()) {
if (pred(range.front())) {
octa::swap(range.front(), ret.front());
@ -29,8 +29,8 @@ _R partition(_R range, _U pred) {
return ret;
}
template<typename _R, typename _P>
bool is_partitioned(_R range, _P pred) {
template<typename R, typename P>
bool is_partitioned(R range, P pred) {
for (; !range.empty() && pred(range.front()); range.pop_front());
for (; !range.empty(); range.pop_front())
if (pred(range.front())) return false;
@ -40,12 +40,12 @@ bool is_partitioned(_R range, _P pred) {
/* sorting */
namespace detail {
template<typename _R, typename _C>
void insort(_R range, _C compare) {
octa::RangeSize<_R> rlen = range.size();
for (octa::RangeSize<_R> i = 1; i < rlen; ++i) {
octa::RangeSize<_R> j = i;
octa::RangeReference<_R> v = range[i];
template<typename R, typename C>
void insort(R range, C compare) {
octa::RangeSize<R> rlen = range.size();
for (octa::RangeSize<R> i = 1; i < rlen; ++i) {
octa::RangeSize<R> j = i;
octa::RangeReference<R> v = range[i];
while (j > 0 && !compare(range[j - 1], v)) {
range[j] = range[j - 1];
--j;
@ -54,20 +54,20 @@ namespace detail {
}
}
template<typename _T, typename _U>
template<typename T, typename U>
struct UnaryCompare {
const _T &val;
_U comp;
bool operator()(const _T &v) const { return comp(v, val); }
const T &val;
U comp;
bool operator()(const T &v) const { return comp(v, val); }
};
template<typename _R, typename _C>
void hs_sift_down(_R range, octa::RangeSize<_R> s,
octa::RangeSize<_R> e, _C compare) {
octa::RangeSize<_R> r = s;
template<typename R, typename C>
void hs_sift_down(R range, octa::RangeSize<R> s,
octa::RangeSize<R> e, C compare) {
octa::RangeSize<R> r = s;
while ((r * 2 + 1) <= e) {
octa::RangeSize<_R> ch = r * 2 + 1;
octa::RangeSize<_R> sw = r;
octa::RangeSize<R> ch = r * 2 + 1;
octa::RangeSize<R> sw = r;
if (compare(range[sw], range[ch]))
sw = ch;
if (((ch + 1) <= e) && compare(range[sw], range[ch + 1]))
@ -79,15 +79,15 @@ namespace detail {
}
}
template<typename _R, typename _C>
void heapsort(_R range, _C compare) {
octa::RangeSize<_R> len = range.size();
octa::RangeSize<_R> st = (len - 2) / 2;
template<typename R, typename C>
void heapsort(R range, C compare) {
octa::RangeSize<R> len = range.size();
octa::RangeSize<R> st = (len - 2) / 2;
for (;;) {
octa::detail::hs_sift_down(range, st, len - 1, compare);
if (st-- == 0) break;
}
octa::RangeSize<_R> e = len - 1;
octa::RangeSize<R> e = len - 1;
while (e > 0) {
octa::swap(range[e], range[0]);
--e;
@ -95,8 +95,8 @@ namespace detail {
}
}
template<typename _R, typename _C>
void introloop(_R range, _C compare, RangeSize<_R> depth) {
template<typename R, typename C>
void introloop(R range, C compare, RangeSize<R> depth) {
if (range.size() <= 10) {
octa::detail::insort(range, compare);
return;
@ -105,201 +105,201 @@ namespace detail {
octa::detail::heapsort(range, compare);
return;
}
octa::RangeReference<_R> p = range[range.size() / 2];
octa::RangeReference<R> p = range[range.size() / 2];
octa::swap(p, range.back());
_R r = octa::partition(range,
octa::detail::UnaryCompare<decltype(p), _C>{ p, compare });
_R l = range.slice(0, range.size() - r.size());
R r = octa::partition(range,
octa::detail::UnaryCompare<decltype(p), C>{ p, compare });
R l = range.slice(0, range.size() - r.size());
octa::swap(r.front(), r.back());
octa::detail::introloop(l, compare, depth - 1);
octa::detail::introloop(r, compare, depth - 1);
}
template<typename _R, typename _C>
void introsort(_R range, _C compare) {
octa::detail::introloop(range, compare, octa::RangeSize<_R>(2
template<typename R, typename C>
void introsort(R range, C compare) {
octa::detail::introloop(range, compare, octa::RangeSize<R>(2
* (log(range.size()) / log(2))));
}
} /* namespace detail */
template<typename _R, typename _C>
void sort(_R range, _C compare) {
template<typename R, typename C>
void sort(R range, C compare) {
octa::detail::introsort(range, compare);
}
template<typename _R>
void sort(_R range) {
sort(range, octa::Less<RangeValue<_R>>());
template<typename R>
void sort(R range) {
sort(range, octa::Less<RangeValue<R>>());
}
/* min/max(_element) */
template<typename _T>
inline const _T &min(const _T &a, const _T &b) {
template<typename T>
inline const T &min(const T &a, const T &b) {
return (a < b) ? a : b;
}
template<typename _T, typename _C>
inline const _T &min(const _T &a, const _T &b, _C compare) {
template<typename T, typename C>
inline const T &min(const T &a, const T &b, C compare) {
return compare(a, b) ? a : b;
}
template<typename _T>
inline const _T &max(const _T &a, const _T &b) {
template<typename T>
inline const T &max(const T &a, const T &b) {
return (a < b) ? b : a;
}
template<typename _T, typename _C>
inline const _T &max(const _T &a, const _T &b, _C compare) {
template<typename T, typename C>
inline const T &max(const T &a, const T &b, C compare) {
return compare(a, b) ? b : a;
}
template<typename _R>
inline _R min_element(_R range) {
_R r = range;
template<typename R>
inline R min_element(R range) {
R r = range;
for (; !range.empty(); range.pop_front())
if (octa::min(r.front(), range.front()) == range.front())
r = range;
return r;
}
template<typename _R, typename _C>
inline _R min_element(_R range, _C compare) {
_R r = range;
template<typename R, typename C>
inline R min_element(R range, C compare) {
R r = range;
for (; !range.empty(); range.pop_front())
if (octa::min(r.front(), range.front(), compare) == range.front())
r = range;
return r;
}
template<typename _R>
inline _R max_element(_R range) {
_R r = range;
template<typename R>
inline R max_element(R range) {
R r = range;
for (; !range.empty(); range.pop_front())
if (octa::max(r.front(), range.front()) == range.front())
r = range;
return r;
}
template<typename _R, typename _C>
inline _R max_element(_R range, _C compare) {
_R r = range;
template<typename R, typename C>
inline R max_element(R range, C compare) {
R r = range;
for (; !range.empty(); range.pop_front())
if (octa::max(r.front(), range.front(), compare) == range.front())
r = range;
return r;
}
template<typename _T>
inline _T min(std::initializer_list<_T> il) {
template<typename T>
inline T min(std::initializer_list<T> il) {
return octa::min_element(octa::each(il)).front();
}
template<typename _T, typename _C>
inline _T min(std::initializer_list<_T> il, _C compare) {
template<typename T, typename C>
inline T min(std::initializer_list<T> il, C compare) {
return octa::min_element(octa::each(il), compare).front();
}
template<typename _T>
inline _T max(std::initializer_list<_T> il) {
template<typename T>
inline T max(std::initializer_list<T> il) {
return octa::max_element(octa::each(il)).front();
}
template<typename _T, typename _C>
inline _T max(std::initializer_list<_T> il, _C compare) {
template<typename T, typename C>
inline T max(std::initializer_list<T> il, C compare) {
return octa::max_element(octa::each(il), compare).front();
}
/* clamp */
template<typename _T, typename _U>
inline _T clamp(const _T &v, const _U &lo, const _U &hi) {
return octa::max(_T(lo), octa::min(v, _T(hi)));
template<typename T, typename U>
inline T clamp(const T &v, const U &lo, const U &hi) {
return octa::max(T(lo), octa::min(v, T(hi)));
}
template<typename _T, typename _U, typename _C>
inline _T clamp(const _T &v, const _U &lo, const _U &hi, _C compare) {
return octa::max(_T(lo), octa::min(v, _T(hi), compare), compare);
template<typename T, typename U, typename C>
inline T clamp(const T &v, const U &lo, const U &hi, C compare) {
return octa::max(T(lo), octa::min(v, T(hi), compare), compare);
}
/* algos that don't change the range */
template<typename _R, typename _F>
_F for_each(_R range, _F func) {
template<typename R, typename F>
F for_each(R range, F func) {
for (; !range.empty(); range.pop_front())
func(range.front());
return octa::move(func);
}
template<typename _R, typename _P>
bool all_of(_R range, _P pred) {
template<typename R, typename P>
bool all_of(R range, P pred) {
for (; !range.empty(); range.pop_front())
if (!pred(range.front())) return false;
return true;
}
template<typename _R, typename _P>
bool any_of(_R range, _P pred) {
template<typename R, typename P>
bool any_of(R range, P pred) {
for (; !range.empty(); range.pop_front())
if (pred(range.front())) return true;
return false;
}
template<typename _R, typename _P>
bool none_of(_R range, _P pred) {
template<typename R, typename P>
bool none_of(R range, P pred) {
for (; !range.empty(); range.pop_front())
if (pred(range.front())) return false;
return true;
}
template<typename _R, typename _T>
_R find(_R range, const _T &v) {
template<typename R, typename T>
R find(R range, const T &v) {
for (; !range.empty(); range.pop_front())
if (range.front() == v)
break;
return range;
}
template<typename _R, typename _P>
_R find_if(_R range, _P pred) {
template<typename R, typename P>
R find_if(R range, P pred) {
for (; !range.empty(); range.pop_front())
if (pred(range.front()))
break;
return range;
}
template<typename _R, typename _P>
_R find_if_not(_R range, _P pred) {
template<typename R, typename P>
R find_if_not(R range, P pred) {
for (; !range.empty(); range.pop_front())
if (!pred(range.front()))
break;
return range;
}
template<typename _R, typename _T>
RangeSize<_R> count(_R range, const _T &v) {
RangeSize<_R> ret = 0;
template<typename R, typename T>
RangeSize<R> count(R range, const T &v) {
RangeSize<R> ret = 0;
for (; !range.empty(); range.pop_front())
if (range.front() == v)
++ret;
return ret;
}
template<typename _R, typename _P>
RangeSize<_R> count_if(_R range, _P pred) {
RangeSize<_R> ret = 0;
template<typename R, typename P>
RangeSize<R> count_if(R range, P pred) {
RangeSize<R> ret = 0;
for (; !range.empty(); range.pop_front())
if (pred(range.front()))
++ret;
return ret;
}
template<typename _R, typename _P>
RangeSize<_R> count_if_not(_R range, _P pred) {
RangeSize<_R> ret = 0;
template<typename R, typename P>
RangeSize<R> count_if_not(R range, P pred) {
RangeSize<R> ret = 0;
for (; !range.empty(); range.pop_front())
if (!pred(range.front()))
++ret;
return ret;
}
template<typename _R>
bool equal(_R range1, _R range2) {
template<typename R>
bool equal(R range1, R range2) {
for (; !range1.empty(); range1.pop_front()) {
if (range2.empty() || (range1.front() != range2.front()))
return false;
@ -310,38 +310,38 @@ bool equal(_R range1, _R range2) {
/* algos that modify ranges or work with output ranges */
template<typename _R1, typename _R2>
_R2 copy(_R1 irange, _R2 orange) {
template<typename R1, typename R2>
R2 copy(R1 irange, R2 orange) {
for (; !irange.empty(); irange.pop_front())
orange.put(irange.front());
return orange;
}
template<typename _R1, typename _R2, typename _P>
_R2 copy_if(_R1 irange, _R2 orange, _P pred) {
template<typename R1, typename R2, typename P>
R2 copy_if(R1 irange, R2 orange, P pred) {
for (; !irange.empty(); irange.pop_front())
if (pred(irange.front()))
orange.put(irange.front());
return orange;
}
template<typename _R1, typename _R2, typename _P>
_R2 copy_if_not(_R1 irange, _R2 orange, _P pred) {
template<typename R1, typename R2, typename P>
R2 copy_if_not(R1 irange, R2 orange, P pred) {
for (; !irange.empty(); irange.pop_front())
if (!pred(irange.front()))
orange.put(irange.front());
return orange;
}
template<typename _R1, typename _R2>
_R2 move(_R1 irange, _R2 orange) {
template<typename R1, typename R2>
R2 move(R1 irange, R2 orange) {
for (; !irange.empty(); irange.pop_front())
orange.put(octa::move(irange.front()));
return orange;
}
template<typename _R>
void reverse(_R range) {
template<typename R>
void reverse(R range) {
while (!range.empty()) {
octa::swap(range.front(), range.back());
range.pop_front();
@ -349,27 +349,27 @@ void reverse(_R range) {
}
}
template<typename _R1, typename _R2>
_R2 reverse_copy(_R1 irange, _R2 orange) {
template<typename R1, typename R2>
R2 reverse_copy(R1 irange, R2 orange) {
for (; !irange.empty(); irange.pop_back())
orange.put(irange.back());
return orange;
}
template<typename _R, typename _T>
void fill(_R range, const _T &v) {
template<typename R, typename T>
void fill(R range, const T &v) {
for (; !range.empty(); range.pop_front())
range.front() = v;
}
template<typename _R, typename _F>
void generate(_R range, _F gen) {
template<typename R, typename F>
void generate(R range, F gen) {
for (; !range.empty(); range.pop_front())
range.front() = gen();
}
template<typename _R1, typename _R2>
octa::Pair<_R1, _R2> swap_ranges(_R1 range1, _R2 range2) {
template<typename R1, typename R2>
octa::Pair<R1, R2> swap_ranges(R1 range1, R2 range2) {
while (!range1.empty() && !range2.empty()) {
octa::swap(range1.front(), range2.front());
range1.pop_front();
@ -378,52 +378,52 @@ octa::Pair<_R1, _R2> swap_ranges(_R1 range1, _R2 range2) {
return octa::make_pair(range1, range2);
}
template<typename _R, typename _T>
void iota(_R range, _T value) {
template<typename R, typename T>
void iota(R range, T value) {
for (; !range.empty(); range.pop_front())
range.front() = value++;
}
template<typename _R, typename _T>
_T foldl(_R range, _T init) {
template<typename R, typename T>
T foldl(R range, T init) {
for (; !range.empty(); range.pop_front())
init = init + range.front();
return init;
}
template<typename _R, typename _T, typename _F>
_T foldl(_R range, _T init, _F func) {
template<typename R, typename T, typename F>
T foldl(R range, T init, F func) {
for (; !range.empty(); range.pop_front())
init = func(init, range.front());
return init;
}
template<typename _R, typename _T>
_T foldr(_R range, _T init) {
template<typename R, typename T>
T foldr(R range, T init) {
for (; !range.empty(); range.pop_back())
init = init + range.back();
return init;
}
template<typename _R, typename _T, typename _F>
_T foldr(_R range, _T init, _F func) {
template<typename R, typename T, typename F>
T foldr(R range, T init, F func) {
for (; !range.empty(); range.pop_back())
init = func(init, range.back());
return init;
}
template<typename _T, typename _R>
template<typename T, typename R>
struct MapRange: InputRange<
MapRange<_T, _R>, octa::RangeCategory<_T>, _R, _R, octa::RangeSize<_T>
MapRange<T, R>, octa::RangeCategory<T>, R, R, octa::RangeSize<T>
> {
private:
_T p_range;
octa::Function<_R(octa::RangeReference<_T>)> p_func;
T p_range;
octa::Function<R(octa::RangeReference<T>)> p_func;
public:
MapRange(): p_range(), p_func() {}
template<typename _F>
MapRange(const _T &range, const _F &func):
template<typename F>
MapRange(const T &range, const F &func):
p_range(range), p_func(func) {}
MapRange(const MapRange &it):
p_range(it.p_range), p_func(it.p_func) {}
@ -442,7 +442,7 @@ public:
}
bool empty() const { return p_range.empty(); }
octa::RangeSize<_T> size() const { return p_range.size(); }
octa::RangeSize<T> size() const { return p_range.size(); }
bool equals_front(const MapRange &r) const {
return p_range.equals_front(r.p_range);
@ -451,10 +451,10 @@ public:
return p_range.equals_front(r.p_range);
}
octa::RangeDifference<_T> distance_front(const MapRange &r) const {
octa::RangeDifference<T> distance_front(const MapRange &r) const {
return p_range.distance_front(r.p_range);
}
octa::RangeDifference<_T> distance_back(const MapRange &r) const {
octa::RangeDifference<T> distance_back(const MapRange &r) const {
return p_range.distance_back(r.p_range);
}
@ -464,54 +464,54 @@ public:
bool push_front() { return p_range.pop_front(); }
bool push_back() { return p_range.push_back(); }
octa::RangeSize<_T> pop_front_n(octa::RangeSize<_T> n) {
octa::RangeSize<T> pop_front_n(octa::RangeSize<T> n) {
p_range.pop_front_n(n);
}
octa::RangeSize<_T> pop_back_n(octa::RangeSize<_T> n) {
octa::RangeSize<T> pop_back_n(octa::RangeSize<T> n) {
p_range.pop_back_n(n);
}
octa::RangeSize<_T> push_front_n(octa::RangeSize<_T> n) {
octa::RangeSize<T> push_front_n(octa::RangeSize<T> n) {
return p_range.push_front_n(n);
}
octa::RangeSize<_T> push_back_n(octa::RangeSize<_T> n) {
octa::RangeSize<T> push_back_n(octa::RangeSize<T> n) {
return p_range.push_back_n(n);
}
_R front() const { return p_func(p_range.front()); }
_R back() const { return p_func(p_range.back()); }
R front() const { return p_func(p_range.front()); }
R back() const { return p_func(p_range.back()); }
_R operator[](octa::RangeSize<_T> idx) const {
R operator[](octa::RangeSize<T> idx) const {
return p_func(p_range[idx]);
}
MapRange<_T, _R> slice(octa::RangeSize<_T> start,
octa::RangeSize<_T> end) {
return MapRange<_T, _R>(p_range.slice(start, end), p_func);
MapRange<T, R> slice(octa::RangeSize<T> start,
octa::RangeSize<T> end) {
return MapRange<T, R>(p_range.slice(start, end), p_func);
}
};
namespace detail {
template<typename _R, typename _F> using MapReturnType
= decltype(declval<_F>()(octa::declval<octa::RangeReference<_R>>()));
template<typename R, typename F> using MapReturnType
= decltype(declval<F>()(octa::declval<octa::RangeReference<R>>()));
}
template<typename _R, typename _F>
MapRange<_R, octa::detail::MapReturnType<_R, _F>> map(_R range,
_F func) {
return octa::MapRange<_R, octa::detail::MapReturnType<_R, _F>>(range,
template<typename R, typename F>
MapRange<R, octa::detail::MapReturnType<R, F>> map(R range,
F func) {
return octa::MapRange<R, octa::detail::MapReturnType<R, F>>(range,
func);
}
template<typename _T>
template<typename T>
struct FilterRange: InputRange<
FilterRange<_T>, octa::CommonType<octa::RangeCategory<_T>,
FilterRange<T>, octa::CommonType<octa::RangeCategory<T>,
octa::ForwardRangeTag>,
octa::RangeValue<_T>, octa::RangeReference<_T>, octa::RangeSize<_T>
octa::RangeValue<T>, octa::RangeReference<T>, octa::RangeSize<T>
> {
private:
_T p_range;
octa::Function<bool(octa::RangeReference<_T>)> p_pred;
T p_range;
octa::Function<bool(octa::RangeReference<T>)> p_pred;
void advance_valid() {
while (!p_range.empty() && !p_pred(front())) p_range.pop_front();
@ -520,8 +520,8 @@ private:
public:
FilterRange(): p_range(), p_pred() {}
template<typename _P>
FilterRange(const _T &range, const _P &pred): p_range(range),
template<typename P>
FilterRange(const T &range, const P &pred): p_range(range),
p_pred(pred) {
advance_valid();
}
@ -559,7 +559,7 @@ public:
return ret;
}
bool push_front() {
_T tmp = p_range;
T tmp = p_range;
if (!tmp.push_front()) return false;
while (!p_pred(tmp.front()))
if (!tmp.push_front())
@ -568,12 +568,12 @@ public:
return true;
}
octa::RangeReference<_T> front() const { return p_range.front(); }
octa::RangeReference<T> front() const { return p_range.front(); }
};
template<typename _R, typename _P>
FilterRange<_R> filter(_R range, _P pred) {
return octa::FilterRange<_R>(range, pred);
template<typename R, typename P>
FilterRange<R> filter(R range, P pred) {
return octa::FilterRange<R>(range, pred);
}
} /* namespace octa */

View File

@ -14,55 +14,55 @@
namespace octa {
template<typename _T, size_t _N>
template<typename T, size_t N>
struct Array {
typedef size_t Size;
typedef ptrdiff_t Difference;
typedef _T Value;
typedef _T &Reference;
typedef const _T &ConstReference;
typedef _T *Pointer;
typedef const _T *ConstPointer;
typedef PointerRange< _T> Range;
typedef PointerRange<const _T> ConstRange;
typedef T Value;
typedef T &Reference;
typedef const T &ConstReference;
typedef T *Pointer;
typedef const T *ConstPointer;
typedef PointerRange< T> Range;
typedef PointerRange<const T> ConstRange;
_T &operator[](size_t i) { return p_buf[i]; }
const _T &operator[](size_t i) const { return p_buf[i]; }
T &operator[](size_t i) { return p_buf[i]; }
const T &operator[](size_t i) const { return p_buf[i]; }
_T &at(size_t i) { return p_buf[i]; }
const _T &at(size_t i) const { return p_buf[i]; }
T &at(size_t i) { return p_buf[i]; }
const T &at(size_t i) const { return p_buf[i]; }
_T &front() { return p_buf[0]; }
const _T &front() const { return p_buf[0]; }
T &front() { return p_buf[0]; }
const T &front() const { return p_buf[0]; }
_T &back() { return p_buf[(_N > 0) ? (_N - 1) : 0]; }
const _T &back() const { return p_buf[(_N > 0) ? (_N - 1) : 0]; }
T &back() { return p_buf[(N > 0) ? (N - 1) : 0]; }
const T &back() const { return p_buf[(N > 0) ? (N - 1) : 0]; }
size_t size() const { return _N; }
size_t size() const { return N; }
bool empty() const { return _N == 0; }
bool empty() const { return N == 0; }
bool in_range(size_t idx) { return idx < _N; }
bool in_range(int idx) { return idx >= 0 && size_t(idx) < _N; }
bool in_range(const _T *ptr) {
return ptr >= &p_buf[0] && ptr < &p_buf[_N];
bool in_range(size_t idx) { return idx < N; }
bool in_range(int idx) { return idx >= 0 && size_t(idx) < N; }
bool in_range(const T *ptr) {
return ptr >= &p_buf[0] && ptr < &p_buf[N];
}
_T *data() { return p_buf; }
const _T *data() const { return p_buf; }
T *data() { return p_buf; }
const T *data() const { return p_buf; }
Range each() {
return octa::PointerRange<_T>(p_buf, p_buf + _N);
return octa::PointerRange<T>(p_buf, p_buf + N);
}
ConstRange each() const {
return octa::PointerRange<const _T>(p_buf, p_buf + _N);
return octa::PointerRange<const T>(p_buf, p_buf + N);
}
void swap(Array &v) {
octa::swap_ranges(each(), v.each());
}
_T p_buf[(_N > 0) ? _N : 1];
T p_buf[(N > 0) ? N : 1];
};
} /* namespace octa */

File diff suppressed because it is too large Load Diff

View File

@ -16,12 +16,12 @@ namespace octa {
/* basic function objects */
#define OCTA_DEFINE_BINARY_OP(_name, _op, _rettype) \
template<typename _T> struct _name { \
_rettype operator()(const _T &x, const _T &y) const { \
template<typename T> struct _name { \
_rettype operator()(const T &x, const T &y) const { \
return x _op y; \
} \
typedef _T FirstArgument; \
typedef _T SecondArgument; \
typedef T FirstArgument; \
typedef T SecondArgument; \
typedef _rettype Result; \
};
@ -33,80 +33,80 @@ OCTA_DEFINE_BINARY_OP(Equal, ==, bool)
OCTA_DEFINE_BINARY_OP(NotEqual, !=, bool)
OCTA_DEFINE_BINARY_OP(LogicalAnd, &&, bool)
OCTA_DEFINE_BINARY_OP(LogicalOr, ||, bool)
OCTA_DEFINE_BINARY_OP(Modulus, %, _T)
OCTA_DEFINE_BINARY_OP(Multiplies, *, _T)
OCTA_DEFINE_BINARY_OP(Divides, /, _T)
OCTA_DEFINE_BINARY_OP(Plus, +, _T)
OCTA_DEFINE_BINARY_OP(Minus, -, _T)
OCTA_DEFINE_BINARY_OP(BitAnd, &, _T)
OCTA_DEFINE_BINARY_OP(BitOr, |, _T)
OCTA_DEFINE_BINARY_OP(BitXor, ^, _T)
OCTA_DEFINE_BINARY_OP(Modulus, %, T)
OCTA_DEFINE_BINARY_OP(Multiplies, *, T)
OCTA_DEFINE_BINARY_OP(Divides, /, T)
OCTA_DEFINE_BINARY_OP(Plus, +, T)
OCTA_DEFINE_BINARY_OP(Minus, -, T)
OCTA_DEFINE_BINARY_OP(BitAnd, &, T)
OCTA_DEFINE_BINARY_OP(BitOr, |, T)
OCTA_DEFINE_BINARY_OP(BitXor, ^, T)
#undef OCTA_DEFINE_BINARY_OP
template<typename _T> struct LogicalNot {
bool operator()(const _T &x) const { return !x; }
typedef _T Argument;
template<typename T> struct LogicalNot {
bool operator()(const T &x) const { return !x; }
typedef T Argument;
typedef bool Result;
};
template<typename _T> struct Negate {
bool operator()(const _T &x) const { return -x; }
typedef _T Argument;
typedef _T Result;
template<typename T> struct Negate {
bool operator()(const T &x) const { return -x; }
typedef T Argument;
typedef T Result;
};
template<typename _T> struct BinaryNegate {
typedef typename _T::FirstArgument FirstArgument;
typedef typename _T::SecondArgument SecondArgument;
template<typename T> struct BinaryNegate {
typedef typename T::FirstArgument FirstArgument;
typedef typename T::SecondArgument SecondArgument;
typedef bool Result;
explicit BinaryNegate(const _T &f): p_fn(f) {}
explicit BinaryNegate(const T &f): p_fn(f) {}
bool operator()(const FirstArgument &x,
const SecondArgument &y) {
return !p_fn(x, y);
}
private:
_T p_fn;
T p_fn;
};
template<typename _T> struct UnaryNegate {
typedef typename _T::Argument Argument;
template<typename T> struct UnaryNegate {
typedef typename T::Argument Argument;
typedef bool Result;
explicit UnaryNegate(const _T &f): p_fn(f) {}
explicit UnaryNegate(const T &f): p_fn(f) {}
bool operator()(const Argument &x) {
return !p_fn(x);
}
private:
_T p_fn;
T p_fn;
};
template<typename _T> UnaryNegate<_T> not1(const _T &fn) {
return UnaryNegate<_T>(fn);
template<typename T> UnaryNegate<T> not1(const T &fn) {
return UnaryNegate<T>(fn);
}
template<typename _T> BinaryNegate<_T> not2(const _T &fn) {
return BinaryNegate<_T>(fn);
template<typename T> BinaryNegate<T> not2(const T &fn) {
return BinaryNegate<T>(fn);
}
/* hash */
template<typename _T> struct Hash;
template<typename T> struct Hash;
namespace detail {
template<typename _T> struct HashBase {
typedef _T Argument;
template<typename T> struct HashBase {
typedef T Argument;
typedef size_t Result;
size_t operator()(_T v) const {
size_t operator()(T v) const {
return size_t(v);
}
};
}
#define OCTA_HASH_BASIC(_T) template<> struct Hash<_T>: octa::detail::HashBase<_T> {};
#define OCTA_HASH_BASIC(T) template<> struct Hash<T>: octa::detail::HashBase<T> {};
OCTA_HASH_BASIC(bool)
OCTA_HASH_BASIC(char)
@ -132,60 +132,60 @@ namespace detail {
return h;
}
template<typename _T, size_t = sizeof(_T) / sizeof(size_t)>
template<typename T, size_t = sizeof(T) / sizeof(size_t)>
struct ScalarHash;
template<typename _T> struct ScalarHash<_T, 0> {
typedef _T Argument;
template<typename T> struct ScalarHash<T, 0> {
typedef T Argument;
typedef size_t Result;
size_t operator()(_T v) const {
union { _T v; size_t h; } u;
size_t operator()(T v) const {
union { T v; size_t h; } u;
u.h = 0;
u.v = v;
return u.h;
}
};
template<typename _T> struct ScalarHash<_T, 1> {
typedef _T Argument;
template<typename T> struct ScalarHash<T, 1> {
typedef T Argument;
typedef size_t Result;
size_t operator()(_T v) const {
union { _T v; size_t h; } u;
size_t operator()(T v) const {
union { T v; size_t h; } u;
u.v = v;
return u.h;
}
};
template<typename _T> struct ScalarHash<_T, 2> {
typedef _T Argument;
template<typename T> struct ScalarHash<T, 2> {
typedef T Argument;
typedef size_t Result;
size_t operator()(_T v) const {
union { _T v; struct { size_t h1, h2; }; } u;
size_t operator()(T v) const {
union { T v; struct { size_t h1, h2; }; } u;
u.v = v;
return mem_hash((const void *)&u, sizeof(u));
}
};
template<typename _T> struct ScalarHash<_T, 3> {
typedef _T Argument;
template<typename T> struct ScalarHash<T, 3> {
typedef T Argument;
typedef size_t Result;
size_t operator()(_T v) const {
union { _T v; struct { size_t h1, h2, h3; }; } u;
size_t operator()(T v) const {
union { T v; struct { size_t h1, h2, h3; }; } u;
u.v = v;
return mem_hash((const void *)&u, sizeof(u));
}
};
template<typename _T> struct ScalarHash<_T, 4> {
typedef _T Argument;
template<typename T> struct ScalarHash<T, 4> {
typedef T Argument;
typedef size_t Result;
size_t operator()(_T v) const {
union { _T v; struct { size_t h1, h2, h3, h4; }; } u;
size_t operator()(T v) const {
union { T v; struct { size_t h1, h2, h3, h4; }; } u;
u.v = v;
return mem_hash((const void *)&u, sizeof(u));
}
@ -230,12 +230,12 @@ template<> struct Hash<ldouble>: octa::detail::ScalarHash<ldouble> {
}
};
template<typename _T> struct Hash<_T *> {
typedef _T *Argument;
template<typename T> struct Hash<T *> {
typedef T *Argument;
typedef size_t Result;
size_t operator()(_T *v) const {
union { _T *v; size_t h; } u;
size_t operator()(T *v) const {
union { T *v; size_t h; } u;
u.v = v;
return octa::detail::mem_hash((const void *)&u, sizeof(u));
}
@ -243,101 +243,101 @@ template<typename _T> struct Hash<_T *> {
/* reference wrapper */
template<typename _T>
template<typename T>
struct ReferenceWrapper {
typedef _T type;
typedef T type;
ReferenceWrapper(_T &v): p_ptr(address_of(v)) {}
ReferenceWrapper(T &v): p_ptr(address_of(v)) {}
ReferenceWrapper(const ReferenceWrapper &) = default;
ReferenceWrapper(_T &&) = delete;
ReferenceWrapper(T &&) = delete;
ReferenceWrapper &operator=(const ReferenceWrapper &) = default;
operator _T &() const { return *p_ptr; }
_T &get() const { return *p_ptr; }
operator T &() const { return *p_ptr; }
T &get() const { return *p_ptr; }
private:
_T *p_ptr;
T *p_ptr;
};
template<typename _T>
ReferenceWrapper<_T> ref(_T &v) {
return ReferenceWrapper<_T>(v);
template<typename T>
ReferenceWrapper<T> ref(T &v) {
return ReferenceWrapper<T>(v);
}
template<typename _T>
ReferenceWrapper<_T> ref(ReferenceWrapper<_T> v) {
return ReferenceWrapper<_T>(v);
template<typename T>
ReferenceWrapper<T> ref(ReferenceWrapper<T> v) {
return ReferenceWrapper<T>(v);
}
template<typename _T> void ref(const _T &&) = delete;
template<typename T> void ref(const T &&) = delete;
template<typename _T>
ReferenceWrapper<const _T> cref(const _T &v) {
return ReferenceWrapper<_T>(v);
template<typename T>
ReferenceWrapper<const T> cref(const T &v) {
return ReferenceWrapper<T>(v);
}
template<typename _T>
ReferenceWrapper<const _T> cref(ReferenceWrapper<_T> v) {
return ReferenceWrapper<_T>(v);
template<typename T>
ReferenceWrapper<const T> cref(ReferenceWrapper<T> v) {
return ReferenceWrapper<T>(v);
}
template<typename _T> void cref(const _T &&) = delete;
template<typename T> void cref(const T &&) = delete;
/* mem_fn */
namespace detail {
template<typename, typename> struct MemTypes;
template<typename _T, typename _R, typename ..._A>
struct MemTypes<_T, _R(_A...)> {
typedef _R Result;
typedef _T Argument;
template<typename T, typename R, typename ...A>
struct MemTypes<T, R(A...)> {
typedef R Result;
typedef T Argument;
};
template<typename _T, typename _R, typename _A>
struct MemTypes<_T, _R(_A)> {
typedef _R Result;
typedef _T FirstArgument;
typedef _A SecondArgument;
template<typename T, typename R, typename A>
struct MemTypes<T, R(A)> {
typedef R Result;
typedef T FirstArgument;
typedef A SecondArgument;
};
template<typename _T, typename _R, typename ..._A>
struct MemTypes<_T, _R(_A...) const> {
typedef _R Result;
typedef const _T Argument;
template<typename T, typename R, typename ...A>
struct MemTypes<T, R(A...) const> {
typedef R Result;
typedef const T Argument;
};
template<typename _T, typename _R, typename _A>
struct MemTypes<_T, _R(_A) const> {
typedef _R Result;
typedef const _T FirstArgument;
typedef _A SecondArgument;
template<typename T, typename R, typename A>
struct MemTypes<T, R(A) const> {
typedef R Result;
typedef const T FirstArgument;
typedef A SecondArgument;
};
template<typename _R, typename _T>
class MemFn: MemTypes<_T, _R> {
_R _T::*p_ptr;
template<typename R, typename T>
class MemFn: MemTypes<T, R> {
R T::*p_ptr;
public:
MemFn(_R _T::*ptr): p_ptr(ptr) {}
template<typename... _A>
auto operator()(_T &obj, _A &&...args) ->
decltype(((obj).*(p_ptr))(forward<_A>(args)...)) {
return ((obj).*(p_ptr))(forward<_A>(args)...);
MemFn(R T::*ptr): p_ptr(ptr) {}
template<typename... A>
auto operator()(T &obj, A &&...args) ->
decltype(((obj).*(p_ptr))(forward<A>(args)...)) {
return ((obj).*(p_ptr))(forward<A>(args)...);
}
template<typename... _A>
auto operator()(const _T &obj, _A &&...args) ->
decltype(((obj).*(p_ptr))(forward<_A>(args)...)) const {
return ((obj).*(p_ptr))(forward<_A>(args)...);
template<typename... A>
auto operator()(const T &obj, A &&...args) ->
decltype(((obj).*(p_ptr))(forward<A>(args)...)) const {
return ((obj).*(p_ptr))(forward<A>(args)...);
}
template<typename... _A>
auto operator()(_T *obj, _A &&...args) ->
decltype(((obj)->*(p_ptr))(forward<_A>(args)...)) {
return ((obj)->*(p_ptr))(forward<_A>(args)...);
template<typename... A>
auto operator()(T *obj, A &&...args) ->
decltype(((obj)->*(p_ptr))(forward<A>(args)...)) {
return ((obj)->*(p_ptr))(forward<A>(args)...);
}
template<typename... _A>
auto operator()(const _T *obj, _A &&...args) ->
decltype(((obj)->*(p_ptr))(forward<_A>(args)...)) const {
return ((obj)->*(p_ptr))(forward<_A>(args)...);
template<typename... A>
auto operator()(const T *obj, A &&...args) ->
decltype(((obj)->*(p_ptr))(forward<A>(args)...)) const {
return ((obj)->*(p_ptr))(forward<A>(args)...);
}
};
} /* namespace detail */
template<typename _R, typename _T>
octa::detail::MemFn<_R, _T> mem_fn(_R _T:: *ptr) {
return octa::detail::MemFn<_R, _T>(ptr);
template<typename R, typename T>
octa::detail::MemFn<R, T> mem_fn(R T:: *ptr) {
return octa::detail::MemFn<R, T>(ptr);
}
/* function impl
@ -351,72 +351,72 @@ namespace detail {
void *p1, *p2;
};
template<typename _T>
template<typename T>
struct FunctorInPlace {
static constexpr bool value = sizeof(_T) <= sizeof(FunctorData)
&& (alignof(FunctorData) % alignof(_T)) == 0
&& octa::IsMoveConstructible<_T>::value;
static constexpr bool value = sizeof(T) <= sizeof(FunctorData)
&& (alignof(FunctorData) % alignof(T)) == 0
&& octa::IsMoveConstructible<T>::value;
};
template<typename _T, typename _E = void>
template<typename T, typename E = void>
struct FunctorDataManager {
template<typename _R, typename ..._A>
static _R call(const FunctorData &s, _A ...args) {
return ((_T &)s)(octa::forward<_A>(args)...);
template<typename R, typename ...A>
static R call(const FunctorData &s, A ...args) {
return ((T &)s)(octa::forward<A>(args)...);
}
static void store_f(FunctorData &s, _T v) {
new (&get_ref(s)) _T(octa::forward<_T>(v));
static void store_f(FunctorData &s, T v) {
new (&get_ref(s)) T(octa::forward<T>(v));
}
static void move_f(FunctorData &lhs, FunctorData &&rhs) {
new (&get_ref(lhs)) _T(octa::move(get_ref(rhs)));
new (&get_ref(lhs)) T(octa::move(get_ref(rhs)));
}
static void destroy_f(FunctorData &s) {
get_ref(s).~_T();
get_ref(s).~T();
}
static _T &get_ref(const FunctorData &s) {
return (_T &)s;
static T &get_ref(const FunctorData &s) {
return (T &)s;
}
};
template<typename _T>
struct FunctorDataManager<_T,
EnableIf<!FunctorInPlace<_T>::value>
template<typename T>
struct FunctorDataManager<T,
EnableIf<!FunctorInPlace<T>::value>
> {
template<typename _R, typename ..._A>
static _R call(const FunctorData &s, _A ...args) {
return (*(_T *&)s)(octa::forward<_A>(args)...);
template<typename R, typename ...A>
static R call(const FunctorData &s, A ...args) {
return (*(T *&)s)(octa::forward<A>(args)...);
}
static void store_f(FunctorData &s, _T v) {
new (&get_ptr_ref(s)) _T *(new _T(octa::forward<_T>(v)));
static void store_f(FunctorData &s, T v) {
new (&get_ptr_ref(s)) T *(new T(octa::forward<T>(v)));
}
static void move_f(FunctorData &lhs, FunctorData &&rhs) {
new (&get_ptr_ref(lhs)) _T *(get_ptr_ref(rhs));
new (&get_ptr_ref(lhs)) T *(get_ptr_ref(rhs));
get_ptr_ref(rhs) = nullptr;
}
static void destroy_f(FunctorData &s) {
_T *&ptr = get_ptr_ref(s);
T *&ptr = get_ptr_ref(s);
if (!ptr) return;
delete ptr;
ptr = nullptr;
}
static _T &get_ref(const FunctorData &s) {
static T &get_ref(const FunctorData &s) {
return *get_ptr_ref(s);
}
static _T *&get_ptr_ref(FunctorData &s) {
return (_T *&)s;
static T *&get_ptr_ref(FunctorData &s) {
return (T *&)s;
}
static _T *&get_ptr_ref(const FunctorData &s) {
return (_T *&)s;
static T *&get_ptr_ref(const FunctorData &s) {
return (T *&)s;
}
};
@ -427,16 +427,16 @@ namespace detail {
const FunctionManager *manager;
};
template<typename _T>
template<typename T>
static const FunctionManager &get_default_fm();
struct FunctionManager {
template<typename _T>
template<typename T>
inline static const FunctionManager create_default_manager() {
return FunctionManager {
&call_move_and_destroy<_T>,
&call_copy<_T>,
&call_destroy<_T>
&call_move_and_destroy<T>,
&call_copy<T>,
&call_destroy<T>
};
}
@ -446,53 +446,53 @@ namespace detail {
const FmStorage &rhs);
void (* const call_destroyf)(FmStorage &s);
template<typename _T>
template<typename T>
static void call_move_and_destroy(FmStorage &lhs,
FmStorage &&rhs) {
typedef FunctorDataManager<_T> _spec;
typedef FunctorDataManager<T> _spec;
_spec::move_f(lhs.data, octa::move(rhs.data));
_spec::destroy_f(rhs.data);
lhs.manager = &get_default_fm<_T>();
lhs.manager = &get_default_fm<T>();
}
template<typename _T>
template<typename T>
static void call_copy(FmStorage &lhs,
const FmStorage &rhs) {
typedef FunctorDataManager<_T> _spec;
lhs.manager = &get_default_fm<_T>();
typedef FunctorDataManager<T> _spec;
lhs.manager = &get_default_fm<T>();
_spec::store_f(lhs.data, _spec::get_ref(rhs.data));
}
template<typename _T>
template<typename T>
static void call_destroy(FmStorage &s) {
typedef FunctorDataManager<_T> _spec;
typedef FunctorDataManager<T> _spec;
_spec::destroy_f(s.data);
}
};
template<typename _T>
template<typename T>
inline static const FunctionManager &get_default_fm() {
static const FunctionManager def_manager
= FunctionManager::create_default_manager<_T>();
= FunctionManager::create_default_manager<T>();
return def_manager;
}
template<typename _R, typename...>
template<typename R, typename...>
struct FunctionBase {
typedef _R Result;
typedef R Result;
};
template<typename _R, typename _T>
struct FunctionBase<_R, _T> {
typedef _R Result;
typedef _T Argument;
template<typename R, typename T>
struct FunctionBase<R, T> {
typedef R Result;
typedef T Argument;
};
template<typename _R, typename _T, typename _U>
struct FunctionBase<_R, _T, _U> {
typedef _R Result;
typedef _T FirstArgument;
typedef _U SecondArgument;
template<typename R, typename T, typename U>
struct FunctionBase<R, T, U> {
typedef R Result;
typedef T FirstArgument;
typedef U SecondArgument;
};
template<typename, typename>
@ -500,47 +500,47 @@ namespace detail {
static constexpr bool value = false;
};
template<typename _R, typename ..._A>
struct IsValidFunctor<Function<_R(_A...)>, _R(_A...)> {
template<typename R, typename ...A>
struct IsValidFunctor<Function<R(A...)>, R(A...)> {
static constexpr bool value = false;
};
struct Empty {
};
template<typename _T>
_T func_to_functor(_T &&f) {
return octa::forward<_T>(f);
template<typename T>
T func_to_functor(T &&f) {
return octa::forward<T>(f);
}
template<typename _RR, typename _T, typename ..._AA>
auto func_to_functor(_RR (_T::*f)(_AA...))
template<typename RR, typename T, typename ...AA>
auto func_to_functor(RR (T::*f)(AA...))
-> decltype(mem_fn(f)) {
return mem_fn(f);
}
template<typename _RR, typename _T, typename ..._AA>
auto func_to_functor(_RR (_T::*f)(_AA...) const)
template<typename RR, typename T, typename ...AA>
auto func_to_functor(RR (T::*f)(AA...) const)
-> decltype(mem_fn(f)) {
return mem_fn(f);
}
template<typename _T, typename _R, typename ..._A>
struct IsValidFunctor<_T, _R(_A...)> {
template<typename _U>
static decltype(func_to_functor(octa::declval<_U>())
(octa::declval<_A>()...)) test(_U *);
template<typename T, typename R, typename ...A>
struct IsValidFunctor<T, R(A...)> {
template<typename U>
static decltype(func_to_functor(octa::declval<U>())
(octa::declval<A>()...)) test(U *);
template<typename>
static Empty test(...);
static constexpr bool value = octa::IsConvertible<
decltype(test<_T>(nullptr)), _R
decltype(test<T>(nullptr)), R
>::value;
};
} /* namespace detail */
template<typename _R, typename ..._A>
struct Function<_R(_A...)>: octa::detail::FunctionBase<_R, _A...> {
template<typename R, typename ...A>
struct Function<R(A...)>: octa::detail::FunctionBase<R, A...> {
Function( ) { init_empty(); }
Function(nullptr_t) { init_empty(); }
@ -553,16 +553,16 @@ struct Function<_R(_A...)>: octa::detail::FunctionBase<_R, _A...> {
f.p_stor.manager->call_copyf(p_stor, f.p_stor);
}
template<typename _T>
Function(_T f, EnableIf<
octa::detail::IsValidFunctor<_T, _R(_A...)>::value,
template<typename T>
Function(T f, EnableIf<
octa::detail::IsValidFunctor<T, R(A...)>::value,
octa::detail::Empty
> = octa::detail::Empty()) {
if (func_is_null(f)) {
init_empty();
return;
}
initialize(octa::detail::func_to_functor(octa::forward<_T>(f)));
initialize(octa::detail::func_to_functor(octa::forward<T>(f)));
}
~Function() {
@ -581,8 +581,8 @@ struct Function<_R(_A...)>: octa::detail::FunctionBase<_R, _A...> {
return *this;
};
_R operator()(_A ...args) const {
return p_call(p_stor.data, octa::forward<_A>(args)...);
R operator()(A ...args) const {
return p_call(p_stor.data, octa::forward<A>(args)...);
}
template<typename _F> void assign(_F &&f) {
@ -604,52 +604,52 @@ struct Function<_R(_A...)>: octa::detail::FunctionBase<_R, _A...> {
private:
octa::detail::FmStorage p_stor;
_R (*p_call)(const octa::detail::FunctorData &, _A...);
R (*p_call)(const octa::detail::FunctorData &, A...);
template<typename _T>
void initialize(_T f) {
p_call = &octa::detail::FunctorDataManager<_T>::template call<_R, _A...>;
p_stor.manager = &octa::detail::get_default_fm<_T>();
octa::detail::FunctorDataManager<_T>::store_f(p_stor.data,
octa::forward<_T>(f));
template<typename T>
void initialize(T f) {
p_call = &octa::detail::FunctorDataManager<T>::template call<R, A...>;
p_stor.manager = &octa::detail::get_default_fm<T>();
octa::detail::FunctorDataManager<T>::store_f(p_stor.data,
octa::forward<T>(f));
}
void init_empty() {
typedef _R(*emptyf)(_A...);
typedef R(*emptyf)(A...);
p_call = nullptr;
p_stor.manager = &octa::detail::get_default_fm<emptyf>();
octa::detail::FunctorDataManager<emptyf>::store_f(p_stor.data, nullptr);
}
template<typename _T>
static bool func_is_null(const _T &) { return false; }
template<typename T>
static bool func_is_null(const T &) { return false; }
static bool func_is_null(_R (* const &fptr)(_A...)) {
static bool func_is_null(R (* const &fptr)(A...)) {
return fptr == nullptr;
}
template<typename _RR, typename _T, typename ..._AA>
static bool func_is_null(_RR (_T::* const &fptr)(_AA...)) {
template<typename RR, typename T, typename ...AA>
static bool func_is_null(RR (T::* const &fptr)(AA...)) {
return fptr == nullptr;
}
template<typename _RR, typename _T, typename ..._AA>
static bool func_is_null(_RR (_T::* const &fptr)(_AA...) const) {
template<typename RR, typename T, typename ...AA>
static bool func_is_null(RR (T::* const &fptr)(AA...) const) {
return fptr == nullptr;
}
};
template<typename _T>
bool operator==(nullptr_t, const Function<_T> &rhs) { return !rhs; }
template<typename T>
bool operator==(nullptr_t, const Function<T> &rhs) { return !rhs; }
template<typename _T>
bool operator==(const Function<_T> &lhs, nullptr_t) { return !lhs; }
template<typename T>
bool operator==(const Function<T> &lhs, nullptr_t) { return !lhs; }
template<typename _T>
bool operator!=(nullptr_t, const Function<_T> &rhs) { return rhs; }
template<typename T>
bool operator!=(nullptr_t, const Function<T> &rhs) { return rhs; }
template<typename _T>
bool operator!=(const Function<_T> &lhs, nullptr_t) { return lhs; }
template<typename T>
bool operator!=(const Function<T> &lhs, nullptr_t) { return lhs; }
} /* namespace octa */

View File

@ -14,19 +14,19 @@
/* must be in std namespace otherwise the compiler won't know about it */
namespace std {
template<typename _T>
template<typename T>
class initializer_list {
const _T *p_buf;
const T *p_buf;
size_t p_len;
initializer_list(const _T *v, size_t n): p_buf(v), p_len(n) {}
initializer_list(const T *v, size_t n): p_buf(v), p_len(n) {}
public:
initializer_list(): p_buf(nullptr), p_len(0) {}
size_t size() const { return p_len; }
const _T *begin() const { return p_buf; }
const _T *end() const { return p_buf + p_len; }
const T *begin() const { return p_buf; }
const T *end() const { return p_buf + p_len; }
};
}
@ -36,11 +36,11 @@ public:
namespace octa {
template<typename _T> using InitializerList = std::initializer_list<_T>;
template<typename T> using InitializerList = std::initializer_list<T>;
template<typename _T>
octa::PointerRange<const _T> each(std::initializer_list<_T> init) {
return octa::PointerRange<const _T>(init.begin(), init.end());
template<typename T>
octa::PointerRange<const T> each(std::initializer_list<T> init) {
return octa::PointerRange<const T>(init.begin(), init.end());
}
}

File diff suppressed because it is too large Load Diff

View File

@ -21,21 +21,21 @@ struct BidirectionalRangeTag: ForwardRangeTag {};
struct RandomAccessRangeTag: BidirectionalRangeTag {};
struct FiniteRandomAccessRangeTag: RandomAccessRangeTag {};
template<typename _T> struct RangeHalf;
template<typename T> struct RangeHalf;
#define OCTA_RANGE_TRAIT(_Name, _TypeName) \
#define OCTA_RANGE_TRAIT(Name, TypeName) \
namespace detail { \
template<typename _T> \
struct Range##_Name##Base { \
typedef typename _T::_TypeName Type; \
template<typename T> \
struct Range##Name##Base { \
typedef typename T::TypeName Type; \
}; \
template<typename _T> \
struct Range##_Name##Base<RangeHalf<_T>> { \
typedef typename _T::_TypeName Type; \
template<typename T> \
struct Range##Name##Base<RangeHalf<T>> { \
typedef typename T::TypeName Type; \
}; \
} \
template<typename _T> \
using Range##_Name = typename octa::detail::Range##_Name##Base<_T>::Type;
template<typename T> \
using Range##Name = typename octa::detail::Range##Name##Base<T>::Type;
OCTA_RANGE_TRAIT(Category, Category)
OCTA_RANGE_TRAIT(Size, Size)
@ -47,109 +47,109 @@ OCTA_RANGE_TRAIT(Difference, Difference)
// is input range
template<typename _T, bool = octa::IsConvertible<
RangeCategory<_T>, InputRangeTag
template<typename T, bool = octa::IsConvertible<
RangeCategory<T>, InputRangeTag
>::value> struct IsInputRange: False {};
template<typename _T>
struct IsInputRange<_T, true>: True {};
template<typename T>
struct IsInputRange<T, true>: True {};
// is forward range
template<typename _T, bool = octa::IsConvertible<
RangeCategory<_T>, ForwardRangeTag
template<typename T, bool = octa::IsConvertible<
RangeCategory<T>, ForwardRangeTag
>::value> struct IsForwardRange: False {};
template<typename _T>
struct IsForwardRange<_T, true>: True {};
template<typename T>
struct IsForwardRange<T, true>: True {};
// is bidirectional range
template<typename _T, bool = octa::IsConvertible<
RangeCategory<_T>, BidirectionalRangeTag
template<typename T, bool = octa::IsConvertible<
RangeCategory<T>, BidirectionalRangeTag
>::value> struct IsBidirectionalRange: False {};
template<typename _T>
struct IsBidirectionalRange<_T, true>: True {};
template<typename T>
struct IsBidirectionalRange<T, true>: True {};
// is random access range
template<typename _T, bool = octa::IsConvertible<
RangeCategory<_T>, RandomAccessRangeTag
template<typename T, bool = octa::IsConvertible<
RangeCategory<T>, RandomAccessRangeTag
>::value> struct IsRandomAccessRange: False {};
template<typename _T>
struct IsRandomAccessRange<_T, true>: True {};
template<typename T>
struct IsRandomAccessRange<T, true>: True {};
// is finite random access range
template<typename _T, bool = octa::IsConvertible<
RangeCategory<_T>, FiniteRandomAccessRangeTag
template<typename T, bool = octa::IsConvertible<
RangeCategory<T>, FiniteRandomAccessRangeTag
>::value> struct IsFiniteRandomAccessRange: False {};
template<typename _T>
struct IsFiniteRandomAccessRange<_T, true>: True {};
template<typename T>
struct IsFiniteRandomAccessRange<T, true>: True {};
// is infinite random access range
template<typename _T>
template<typename T>
struct IsInfiniteRandomAccessRange: IntegralConstant<bool,
(IsRandomAccessRange<_T>::value && !IsFiniteRandomAccessRange<_T>::value)
(IsRandomAccessRange<T>::value && !IsFiniteRandomAccessRange<T>::value)
> {};
// is output range
namespace detail {
template<typename _T, typename _P>
template<typename T, typename P>
struct OutputRangeTest {
template<typename _U, void (_U::*)(_P)> struct Test {};
template<typename _U> static char test(Test<_U, &_U::put> *);
template<typename _U> static int test(...);
static constexpr bool value = (sizeof(test<_T>(0)) == sizeof(char));
template<typename U, void (U::*)(P)> struct Test {};
template<typename U> static char test(Test<U, &U::put> *);
template<typename U> static int test(...);
static constexpr bool value = (sizeof(test<T>(0)) == sizeof(char));
};
}
template<typename _T, bool = (octa::IsConvertible<
RangeCategory<_T>, OutputRangeTag
>::value || (IsInputRange<_T>::value &&
(octa::detail::OutputRangeTest<_T, const RangeValue<_T> &>::value ||
octa::detail::OutputRangeTest<_T, RangeValue<_T> &&>::value)
template<typename T, bool = (octa::IsConvertible<
RangeCategory<T>, OutputRangeTag
>::value || (IsInputRange<T>::value &&
(octa::detail::OutputRangeTest<T, const RangeValue<T> &>::value ||
octa::detail::OutputRangeTest<T, RangeValue<T> &&>::value)
))> struct IsOutputRange: False {};
template<typename _T>
struct IsOutputRange<_T, true>: True {};
template<typename T>
struct IsOutputRange<T, true>: True {};
namespace detail {
// range iterator
template<typename _T>
template<typename T>
struct RangeIterator {
RangeIterator(): p_range() {}
explicit RangeIterator(const _T &range): p_range(range) {}
explicit RangeIterator(const T &range): p_range(range) {}
RangeIterator &operator++() {
p_range.pop_front();
return *this;
}
RangeReference<_T> operator*() const {
RangeReference<T> operator*() const {
return p_range.front();
}
bool operator!=(RangeIterator) const { return !p_range.empty(); }
private:
_T p_range;
T p_range;
};
}
// range half
template<typename _T>
template<typename T>
struct RangeHalf {
private:
_T p_range;
T p_range;
public:
typedef _T Range;
typedef T Range;
RangeHalf(): p_range() {}
RangeHalf(const _T &range): p_range(range) {}
RangeHalf(const T &range): p_range(range) {}
RangeHalf(const RangeHalf &half): p_range(half.p_range) {}
RangeHalf(RangeHalf &&half): p_range(octa::move(half.p_range)) {}
@ -163,23 +163,23 @@ public:
return *this;
}
_T range() const { return p_range; }
T range() const { return p_range; }
bool next() { return p_range.pop_front(); }
bool prev() { return p_range.push_front(); }
RangeSize<_T> next_n(RangeSize<_T> n) {
RangeSize<T> next_n(RangeSize<T> n) {
return p_range.pop_front_n(n);
}
RangeSize<_T> prev_n(RangeSize<_T> n) {
RangeSize<T> prev_n(RangeSize<T> n) {
return p_range.push_front_n(n);
}
RangeReference<_T> get() const {
RangeReference<T> get() const {
return p_range.front();
}
RangeDifference<_T> distance(const RangeHalf &half) const {
RangeDifference<T> distance(const RangeHalf &half) const {
return p_range.distance_front(half.p_range);
}
@ -196,11 +196,11 @@ public:
/* iterator like interface */
RangeReference<_T> operator*() const {
RangeReference<T> operator*() const {
return get();
}
RangeReference<_T> operator[](RangeSize<_T> idx) const {
RangeReference<T> operator[](RangeSize<T> idx) const {
return p_range[idx];
}
@ -224,132 +224,132 @@ public:
return octa::move(tmp);
}
RangeHalf operator+(RangeDifference<_T> n) {
RangeHalf operator+(RangeDifference<T> n) {
RangeHalf tmp(*this);
if (n < 0) tmp.prev_n(-n);
else tmp.next_n(n);
return octa::move(tmp);
}
RangeHalf operator-(RangeDifference<_T> n) {
RangeHalf operator-(RangeDifference<T> n) {
RangeHalf tmp(*this);
if (n < 0) tmp.next_n(-n);
else tmp.prev_n(n);
return octa::move(tmp);
}
RangeHalf &operator+=(RangeDifference<_T> n) {
RangeHalf &operator+=(RangeDifference<T> n) {
if (n < 0) prev_n(-n);
else next_n(n);
return *this;
}
RangeHalf &operator-=(RangeDifference<_T> n) {
RangeHalf &operator-=(RangeDifference<T> n) {
if (n < 0) next_n(-n);
else prev_n(n);
return *this;
}
};
template<typename _R>
RangeDifference<_R> operator-(const _R &lhs, const _R &rhs) {
template<typename R>
RangeDifference<R> operator-(const R &lhs, const R &rhs) {
return rhs.distance(lhs);
}
namespace detail {
template<typename _R>
RangeSize<_R> pop_front_n(_R &range, RangeSize<_R> n) {
for (RangeSize<_R> i = 0; i < n; ++i)
template<typename R>
RangeSize<R> pop_front_n(R &range, RangeSize<R> n) {
for (RangeSize<R> i = 0; i < n; ++i)
if (!range.pop_front()) return i;
return n;
}
template<typename _R>
RangeSize<_R> pop_back_n(_R &range, RangeSize<_R> n) {
for (RangeSize<_R> i = 0; i < n; ++i)
template<typename R>
RangeSize<R> pop_back_n(R &range, RangeSize<R> n) {
for (RangeSize<R> i = 0; i < n; ++i)
if (!range.pop_back()) return i;
return n;
}
template<typename _R>
RangeSize<_R> push_front_n(_R &range, RangeSize<_R> n) {
for (RangeSize<_R> i = 0; i < n; ++i)
template<typename R>
RangeSize<R> push_front_n(R &range, RangeSize<R> n) {
for (RangeSize<R> i = 0; i < n; ++i)
if (!range.push_front()) return i;
return n;
}
template<typename _R>
RangeSize<_R> push_back_n(_R &range, RangeSize<_R> n) {
for (RangeSize<_R> i = 0; i < n; ++i)
template<typename R>
RangeSize<R> push_back_n(R &range, RangeSize<R> n) {
for (RangeSize<R> i = 0; i < n; ++i)
if (!range.push_back()) return i;
return n;
}
}
template<typename _B, typename _C, typename _V, typename _R = _V &,
typename _S = size_t, typename _D = ptrdiff_t
template<typename B, typename C, typename V, typename R = V &,
typename S = size_t, typename D = ptrdiff_t
> struct InputRange {
typedef _C Category;
typedef _S Size;
typedef _D Difference;
typedef _V Value;
typedef _R Reference;
typedef C Category;
typedef S Size;
typedef D Difference;
typedef V Value;
typedef R Reference;
octa::detail::RangeIterator<_B> begin() const {
return octa::detail::RangeIterator<_B>((const _B &)*this);
octa::detail::RangeIterator<B> begin() const {
return octa::detail::RangeIterator<B>((const B &)*this);
}
octa::detail::RangeIterator<_B> end() const {
return octa::detail::RangeIterator<_B>();
octa::detail::RangeIterator<B> end() const {
return octa::detail::RangeIterator<B>();
}
Size pop_front_n(Size n) {
return octa::detail::pop_front_n<_B>(*((_B *)this), n);
return octa::detail::pop_front_n<B>(*((B *)this), n);
}
Size pop_back_n(Size n) {
return octa::detail::pop_back_n<_B>(*((_B *)this), n);
return octa::detail::pop_back_n<B>(*((B *)this), n);
}
Size push_front_n(Size n) {
return octa::detail::push_front_n<_B>(*((_B *)this), n);
return octa::detail::push_front_n<B>(*((B *)this), n);
}
Size push_back_n(Size n) {
return octa::detail::push_back_n<_B>(*((_B *)this), n);
return octa::detail::push_back_n<B>(*((B *)this), n);
}
_B each() const {
return _B(*((_B *)this));
B each() const {
return B(*((B *)this));
}
RangeHalf<_B> half() const {
return RangeHalf<_B>(*((_B *)this));
RangeHalf<B> half() const {
return RangeHalf<B>(*((B *)this));
}
};
template<typename _V, typename _R = _V &, typename _S = size_t,
typename _D = ptrdiff_t
template<typename V, typename R = V &, typename S = size_t,
typename D = ptrdiff_t
> struct OutputRange {
typedef OutputRangeTag Category;
typedef _S Size;
typedef _D Difference;
typedef _V Value;
typedef _R Reference;
typedef S Size;
typedef D Difference;
typedef V Value;
typedef R Reference;
};
template<typename _T>
struct ReverseRange: InputRange<ReverseRange<_T>,
RangeCategory<_T>, RangeValue<_T>, RangeReference<_T>, RangeSize<_T>,
RangeDifference<_T>
template<typename T>
struct ReverseRange: InputRange<ReverseRange<T>,
RangeCategory<T>, RangeValue<T>, RangeReference<T>, RangeSize<T>,
RangeDifference<T>
> {
private:
typedef RangeReference<_T> _r_ref;
typedef RangeSize<_T> _r_size;
typedef RangeReference<T> r_ref;
typedef RangeSize<T> r_size;
_T p_range;
T p_range;
public:
ReverseRange(): p_range() {}
ReverseRange(const _T &range): p_range(range) {}
ReverseRange(const T &range): p_range(range) {}
ReverseRange(const ReverseRange &it): p_range(it.p_range) {}
@ -363,17 +363,17 @@ public:
p_range = octa::move(v.p_range);
return *this;
}
ReverseRange &operator=(const _T &v) {
ReverseRange &operator=(const T &v) {
p_range = v;
return *this;
}
ReverseRange &operator=(_T &&v) {
ReverseRange &operator=(T &&v) {
p_range = octa::move(v);
return *this;
}
bool empty() const { return p_range.empty(); }
_r_size size() const { return p_range.size(); }
r_size size() const { return p_range.size(); }
bool equals_front(const ReverseRange &r) const {
return p_range.equals_back(r.p_range);
@ -382,10 +382,10 @@ public:
return p_range.equals_front(r.p_range);
}
RangeDifference<_T> distance_front(const ReverseRange &r) const {
RangeDifference<T> distance_front(const ReverseRange &r) const {
return -p_range.distance_back(r.p_range);
}
RangeDifference<_T> distance_back(const ReverseRange &r) const {
RangeDifference<T> distance_back(const ReverseRange &r) const {
return -p_range.distance_front(r.p_range);
}
@ -395,44 +395,44 @@ public:
bool push_front() { return p_range.push_back(); }
bool push_back() { return p_range.push_front(); }
_r_size pop_front_n(_r_size n) { return p_range.pop_front_n(n); }
_r_size pop_back_n(_r_size n) { return p_range.pop_back_n(n); }
r_size pop_front_n(r_size n) { return p_range.pop_front_n(n); }
r_size pop_back_n(r_size n) { return p_range.pop_back_n(n); }
_r_size push_front_n(_r_size n) { return p_range.push_front_n(n); }
_r_size push_back_n(_r_size n) { return p_range.push_back_n(n); }
r_size push_front_n(r_size n) { return p_range.push_front_n(n); }
r_size push_back_n(r_size n) { return p_range.push_back_n(n); }
_r_ref front() const { return p_range.back(); }
_r_ref back() const { return p_range.front(); }
r_ref front() const { return p_range.back(); }
r_ref back() const { return p_range.front(); }
_r_ref operator[](_r_size i) const { return p_range[size() - i - 1]; }
r_ref operator[](r_size i) const { return p_range[size() - i - 1]; }
ReverseRange<_T> slice(_r_size start, _r_size end) const {
_r_size len = p_range.size();
return ReverseRange<_T>(p_range.slice(len - end, len - start));
ReverseRange<T> slice(r_size start, r_size end) const {
r_size len = p_range.size();
return ReverseRange<T>(p_range.slice(len - end, len - start));
}
};
template<typename _T>
ReverseRange<_T> make_reverse_range(const _T &it) {
return ReverseRange<_T>(it);
template<typename T>
ReverseRange<T> make_reverse_range(const T &it) {
return ReverseRange<T>(it);
}
template<typename _T>
struct MoveRange: InputRange<MoveRange<_T>,
RangeCategory<_T>, RangeValue<_T>, RangeValue<_T> &&, RangeSize<_T>,
RangeDifference<_T>
template<typename T>
struct MoveRange: InputRange<MoveRange<T>,
RangeCategory<T>, RangeValue<T>, RangeValue<T> &&, RangeSize<T>,
RangeDifference<T>
> {
private:
typedef RangeValue<_T> _r_val;
typedef RangeValue<_T> &&_r_ref;
typedef RangeSize<_T> _r_size;
typedef RangeValue<T> r_val;
typedef RangeValue<T> &&r_ref;
typedef RangeSize<T> r_size;
_T p_range;
T p_range;
public:
MoveRange(): p_range() {}
MoveRange(const _T &range): p_range(range) {}
MoveRange(const T &range): p_range(range) {}
MoveRange(const MoveRange &it): p_range(it.p_range) {}
@ -446,17 +446,17 @@ public:
p_range = octa::move(v.p_range);
return *this;
}
MoveRange &operator=(const _T &v) {
MoveRange &operator=(const T &v) {
p_range = v;
return *this;
}
MoveRange &operator=(_T &&v) {
MoveRange &operator=(T &&v) {
p_range = octa::move(v);
return *this;
}
bool empty() const { return p_range.empty(); }
_r_size size() const { return p_range.size(); }
r_size size() const { return p_range.size(); }
bool equals_front(const MoveRange &r) const {
return p_range.equals_front(r.p_range);
@ -465,10 +465,10 @@ public:
return p_range.equals_back(r.p_range);
}
RangeDifference<_T> distance_front(const MoveRange &r) const {
RangeDifference<T> distance_front(const MoveRange &r) const {
return p_range.distance_front(r.p_range);
}
RangeDifference<_T> distance_back(const MoveRange &r) const {
RangeDifference<T> distance_back(const MoveRange &r) const {
return p_range.distance_back(r.p_range);
}
@ -478,38 +478,38 @@ public:
bool push_front() { return p_range.push_front(); }
bool push_back() { return p_range.push_back(); }
_r_size pop_front_n(_r_size n) { return p_range.pop_front_n(n); }
_r_size pop_back_n(_r_size n) { return p_range.pop_back_n(n); }
r_size pop_front_n(r_size n) { return p_range.pop_front_n(n); }
r_size pop_back_n(r_size n) { return p_range.pop_back_n(n); }
_r_size push_front_n(_r_size n) { return p_range.push_front_n(n); }
_r_size push_back_n(_r_size n) { return p_range.push_back_n(n); }
r_size push_front_n(r_size n) { return p_range.push_front_n(n); }
r_size push_back_n(r_size n) { return p_range.push_back_n(n); }
_r_ref front() const { return octa::move(p_range.front()); }
_r_ref back() const { return octa::move(p_range.back()); }
r_ref front() const { return octa::move(p_range.front()); }
r_ref back() const { return octa::move(p_range.back()); }
_r_ref operator[](_r_size i) const { return octa::move(p_range[i]); }
r_ref operator[](r_size i) const { return octa::move(p_range[i]); }
MoveRange<_T> slice(_r_size start, _r_size end) const {
return MoveRange<_T>(p_range.slice(start, end));
MoveRange<T> slice(r_size start, r_size end) const {
return MoveRange<T>(p_range.slice(start, end));
}
void put(const _r_val &v) { p_range.put(v); }
void put(_r_val &&v) { p_range.put(octa::move(v)); }
void put(const r_val &v) { p_range.put(v); }
void put(r_val &&v) { p_range.put(octa::move(v)); }
};
template<typename _T>
MoveRange<_T> make_move_range(const _T &it) {
return MoveRange<_T>(it);
template<typename T>
MoveRange<T> make_move_range(const T &it) {
return MoveRange<T>(it);
}
template<typename _T>
struct NumberRange: InputRange<NumberRange<_T>, ForwardRangeTag, _T, _T> {
template<typename T>
struct NumberRange: InputRange<NumberRange<T>, ForwardRangeTag, T, T> {
NumberRange(): p_a(0), p_b(0), p_step(0) {}
NumberRange(const NumberRange &it): p_a(it.p_a), p_b(it.p_b),
p_step(it.p_step) {}
NumberRange(_T a, _T b, _T step = _T(1)): p_a(a), p_b(b),
NumberRange(T a, T b, T step = T(1)): p_a(a), p_b(b),
p_step(step) {}
NumberRange(_T v): p_a(0), p_b(v), p_step(1) {}
NumberRange(T v): p_a(0), p_b(v), p_step(1) {}
bool empty() const { return p_a * p_step >= p_b * p_step; }
@ -519,29 +519,29 @@ struct NumberRange: InputRange<NumberRange<_T>, ForwardRangeTag, _T, _T> {
bool pop_front() { p_a += p_step; return true; }
bool push_front() { p_a -= p_step; return true; }
_T front() const { return p_a; }
T front() const { return p_a; }
private:
_T p_a, p_b, p_step;
T p_a, p_b, p_step;
};
template<typename _T>
NumberRange<_T> range(_T a, _T b, _T step = _T(1)) {
return NumberRange<_T>(a, b, step);
template<typename T>
NumberRange<T> range(T a, T b, T step = T(1)) {
return NumberRange<T>(a, b, step);
}
template<typename _T>
NumberRange<_T> range(_T v) {
return NumberRange<_T>(v);
template<typename T>
NumberRange<T> range(T v) {
return NumberRange<T>(v);
}
template<typename _T>
struct PointerRange: InputRange<PointerRange<_T>, FiniteRandomAccessRangeTag, _T> {
template<typename T>
struct PointerRange: InputRange<PointerRange<T>, FiniteRandomAccessRangeTag, T> {
PointerRange(): p_beg(nullptr), p_end(nullptr) {}
PointerRange(const PointerRange &v): p_beg(v.p_beg),
p_end(v.p_end) {}
PointerRange(_T *beg, _T *end): p_beg(beg), p_end(end) {}
PointerRange(_T *beg, size_t n): p_beg(beg), p_end(beg + n) {}
PointerRange(T *beg, T *end): p_beg(beg), p_end(end) {}
PointerRange(T *beg, size_t n): p_beg(beg), p_end(beg + n) {}
PointerRange &operator=(const PointerRange &v) {
p_beg = v.p_beg;
@ -575,7 +575,7 @@ struct PointerRange: InputRange<PointerRange<_T>, FiniteRandomAccessRangeTag, _T
p_beg -= n; return true;
}
_T &front() const { return *p_beg; }
T &front() const { return *p_beg; }
bool equals_front(const PointerRange &range) const {
return p_beg == range.p_beg;
@ -609,7 +609,7 @@ struct PointerRange: InputRange<PointerRange<_T>, FiniteRandomAccessRangeTag, _T
p_end += n; return true;
}
_T &back() const { return *(p_end - 1); }
T &back() const { return *(p_end - 1); }
bool equals_back(const PointerRange &range) const {
return p_end == range.p_end;
@ -626,43 +626,43 @@ struct PointerRange: InputRange<PointerRange<_T>, FiniteRandomAccessRangeTag, _T
return PointerRange(p_beg + start, p_beg + end);
}
_T &operator[](size_t i) const { return p_beg[i]; }
T &operator[](size_t i) const { return p_beg[i]; }
/* satisfy OutputRange */
void put(const _T &v) {
void put(const T &v) {
*(p_beg++) = v;
}
void put(_T &&v) {
void put(T &&v) {
*(p_beg++) = octa::move(v);
}
private:
_T *p_beg, *p_end;
T *p_beg, *p_end;
};
template<typename _T, typename _S>
template<typename T, typename S>
struct EnumeratedValue {
_S index;
_T value;
S index;
T value;
};
template<typename _T>
struct EnumeratedRange: InputRange<EnumeratedRange<_T>,
CommonType<RangeCategory<_T>, ForwardRangeTag>, RangeValue<_T>,
EnumeratedValue<RangeReference<_T>, RangeSize<_T>>,
RangeSize<_T>
template<typename T>
struct EnumeratedRange: InputRange<EnumeratedRange<T>,
CommonType<RangeCategory<T>, ForwardRangeTag>, RangeValue<T>,
EnumeratedValue<RangeReference<T>, RangeSize<T>>,
RangeSize<T>
> {
private:
typedef RangeReference<_T> _r_ref;
typedef RangeSize<_T> _r_size;
typedef RangeReference<T> r_ref;
typedef RangeSize<T> r_size;
_T p_range;
_r_size p_index;
T p_range;
r_size p_index;
public:
EnumeratedRange(): p_range(), p_index(0) {}
EnumeratedRange(const _T &range): p_range(range), p_index(0) {}
EnumeratedRange(const T &range): p_range(range), p_index(0) {}
EnumeratedRange(const EnumeratedRange &it):
p_range(it.p_range), p_index(it.p_index) {}
@ -680,12 +680,12 @@ public:
p_index = v.p_index;
return *this;
}
EnumeratedRange &operator=(const _T &v) {
EnumeratedRange &operator=(const T &v) {
p_range = v;
p_index = 0;
return *this;
}
EnumeratedRange &operator=(_T &&v) {
EnumeratedRange &operator=(T &&v) {
p_range = octa::move(v);
p_index = 0;
return *this;
@ -705,33 +705,33 @@ public:
return false;
}
_r_size pop_front_n(_r_size n) {
_r_size ret = p_range.pop_front_n(n);
r_size pop_front_n(r_size n) {
r_size ret = p_range.pop_front_n(n);
p_index += ret;
return ret;
}
EnumeratedValue<_r_ref, _r_size> front() const {
return EnumeratedValue<_r_ref, _r_size> { p_index, p_range.front() };
EnumeratedValue<r_ref, r_size> front() const {
return EnumeratedValue<r_ref, r_size> { p_index, p_range.front() };
}
};
template<typename _T>
EnumeratedRange<_T> enumerate(const _T &it) {
return EnumeratedRange<_T>(it);
template<typename T>
EnumeratedRange<T> enumerate(const T &it) {
return EnumeratedRange<T>(it);
}
template<typename _T>
struct TakeRange: InputRange<TakeRange<_T>,
CommonType<RangeCategory<_T>, ForwardRangeTag>,
RangeValue<_T>, RangeReference<_T>, RangeSize<_T>
template<typename T>
struct TakeRange: InputRange<TakeRange<T>,
CommonType<RangeCategory<T>, ForwardRangeTag>,
RangeValue<T>, RangeReference<T>, RangeSize<T>
> {
private:
_T p_range;
RangeSize<_T> p_remaining;
T p_range;
RangeSize<T> p_remaining;
public:
TakeRange(): p_range(), p_remaining(0) {}
TakeRange(const _T &range, RangeSize<_T> rem): p_range(range),
TakeRange(const T &range, RangeSize<T> rem): p_range(range),
p_remaining(rem) {}
TakeRange(const TakeRange &it): p_range(it.p_range),
p_remaining(it.p_remaining) {}
@ -764,44 +764,44 @@ public:
return false;
}
RangeSize<_T> pop_front_n(RangeSize<_T> n) {
RangeSize<_T> ret = p_range.pop_front_n(n);
RangeSize<T> pop_front_n(RangeSize<T> n) {
RangeSize<T> ret = p_range.pop_front_n(n);
p_remaining -= ret;
return ret;
}
RangeSize<_T> push_front_n(RangeSize<_T> n) {
RangeSize<_T> ret = p_range.push_front_n(n);
RangeSize<T> push_front_n(RangeSize<T> n) {
RangeSize<T> ret = p_range.push_front_n(n);
p_remaining += ret;
return ret;
}
RangeReference<_T> front() const { return p_range.front(); }
RangeReference<T> front() const { return p_range.front(); }
bool equals_front(const TakeRange &r) const {
return p_range.equals_front(r.p_range);
}
RangeDifference<_T> distance_front(const TakeRange &r) const {
RangeDifference<T> distance_front(const TakeRange &r) const {
return p_range.distance_front(r.p_range);
}
};
template<typename _T>
TakeRange<_T> take(const _T &it, RangeSize<_T> n) {
return TakeRange<_T>(it, n);
template<typename T>
TakeRange<T> take(const T &it, RangeSize<T> n) {
return TakeRange<T>(it, n);
}
template<typename _T>
struct ChunksRange: InputRange<ChunksRange<_T>,
CommonType<RangeCategory<_T>, ForwardRangeTag>,
TakeRange<_T>, TakeRange<_T>, RangeSize<_T>
template<typename T>
struct ChunksRange: InputRange<ChunksRange<T>,
CommonType<RangeCategory<T>, ForwardRangeTag>,
TakeRange<T>, TakeRange<T>, RangeSize<T>
> {
private:
_T p_range;
RangeSize<_T> p_chunksize;
T p_range;
RangeSize<T> p_chunksize;
public:
ChunksRange(): p_range(), p_chunksize(0) {}
ChunksRange(const _T &range, RangeSize<_T> chs): p_range(range),
ChunksRange(const T &range, RangeSize<T> chs): p_range(range),
p_chunksize(chs) {}
ChunksRange(const ChunksRange &it): p_range(it.p_range),
p_chunksize(it.p_chunksize) {}
@ -825,19 +825,19 @@ public:
bool pop_front() { return p_range.pop_front_n(p_chunksize) > 0; }
bool push_front() {
_T tmp = p_range;
RangeSize<_T> an = tmp.push_front_n(p_chunksize);
T tmp = p_range;
RangeSize<T> an = tmp.push_front_n(p_chunksize);
if (an != p_chunksize) return false;
p_range = tmp;
return true;
}
RangeSize<_T> pop_front_n(RangeSize<_T> n) {
RangeSize<T> pop_front_n(RangeSize<T> n) {
return p_range.pop_front_n(p_chunksize * n) / p_chunksize;
}
RangeSize<_T> push_front_n(RangeSize<_T> n) {
_T tmp = p_range;
RangeSize<_T> an = tmp.push_front_n(p_chunksize * n);
RangeSize<_T> pn = an / p_chunksize;
RangeSize<T> push_front_n(RangeSize<T> n) {
T tmp = p_range;
RangeSize<T> an = tmp.push_front_n(p_chunksize * n);
RangeSize<T> pn = an / p_chunksize;
if (!pn) return 0;
if (pn == n) {
p_range = tmp;
@ -846,49 +846,49 @@ public:
return p_range.push_front_n(p_chunksize * an) / p_chunksize;
}
TakeRange<_T> front() const { return take(p_range, p_chunksize); }
TakeRange<T> front() const { return take(p_range, p_chunksize); }
};
template<typename _T>
ChunksRange<_T> chunks(const _T &it, RangeSize<_T> chs) {
return ChunksRange<_T>(it, chs);
template<typename T>
ChunksRange<T> chunks(const T &it, RangeSize<T> chs) {
return ChunksRange<T>(it, chs);
}
template<typename _T>
auto each(_T &r) -> decltype(r.each()) {
template<typename T>
auto each(T &r) -> decltype(r.each()) {
return r.each();
}
template<typename _T>
auto each(const _T &r) -> decltype(r.each()) {
template<typename T>
auto each(const T &r) -> decltype(r.each()) {
return r.each();
}
template<typename _T, size_t _N>
PointerRange<_T> each(_T (&array)[_N]) {
return PointerRange<_T>(array, _N);
template<typename T, size_t N>
PointerRange<T> each(T (&array)[N]) {
return PointerRange<T>(array, N);
}
// range of
template<typename _T> using RangeOf = decltype(octa::each(octa::declval<_T>()));
template<typename T> using RangeOf = decltype(octa::each(octa::declval<T>()));
template<typename _T>
struct HalfRange: InputRange<HalfRange<_T>,
RangeCategory<_T>, RangeValue<_T>, RangeReference<_T>, RangeSize<_T>,
RangeDifference<_T>
template<typename T>
struct HalfRange: InputRange<HalfRange<T>,
RangeCategory<T>, RangeValue<T>, RangeReference<T>, RangeSize<T>,
RangeDifference<T>
> {
private:
_T p_beg;
_T p_end;
T p_beg;
T p_end;
public:
HalfRange(): p_beg(), p_end() {}
HalfRange(const HalfRange &range): p_beg(range.p_beg),
p_end(range.p_end) {}
HalfRange(HalfRange &&range): p_beg(octa::move(range.p_beg)),
p_end(octa::move(range.p_end)) {}
HalfRange(const _T &beg, const _T &end): p_beg(beg),
HalfRange(const T &beg, const T &end): p_beg(beg),
p_end(end) {}
HalfRange(_T &&beg, _T &&end): p_beg(octa::move(beg)),
HalfRange(T &&beg, T &&end): p_beg(octa::move(beg)),
p_end(octa::move(end)) {}
HalfRange &operator=(const HalfRange &range) {
@ -920,8 +920,8 @@ public:
return p_end.next();
}
RangeReference<_T> front() const { return *p_beg; }
RangeReference<_T> back() const { return *(p_end - 1); }
RangeReference<T> front() const { return *p_beg; }
RangeReference<T> back() const { return *(p_end - 1); }
bool equals_front(const HalfRange &range) const {
return p_beg == range.p_beg;
@ -930,35 +930,35 @@ public:
return p_end == range.p_end;
}
RangeDifference<_T> distance_front(const HalfRange &range) const {
RangeDifference<T> distance_front(const HalfRange &range) const {
return range.p_beg - p_beg;
}
RangeDifference<_T> distance_back(const HalfRange &range) const {
RangeDifference<T> distance_back(const HalfRange &range) const {
return range.p_end - p_end;
}
RangeSize<_T> size() const { return p_end - p_beg; }
RangeSize<T> size() const { return p_end - p_beg; }
HalfRange<_T> slice(RangeSize<_T> start, RangeSize<_T> p_end) const {
return HalfRange<_T>(p_beg + start, p_beg + p_end);
HalfRange<T> slice(RangeSize<T> start, RangeSize<T> p_end) const {
return HalfRange<T>(p_beg + start, p_beg + p_end);
}
RangeReference<_T> operator[](RangeSize<_T> idx) const {
RangeReference<T> operator[](RangeSize<T> idx) const {
return p_beg[idx];
}
void put(const RangeValue<_T> &v) {
void put(const RangeValue<T> &v) {
p_beg.range().put(v);
}
void put(RangeValue<_T> &&v) {
void put(RangeValue<T> &&v) {
p_beg.range().put(octa::move(v));
}
};
template<typename _T>
HalfRange<RangeHalf<_T>>
make_half_range(const RangeHalf<_T> &a, const RangeHalf<_T> &b) {
return HalfRange<RangeHalf<_T>>(a, b);
template<typename T>
HalfRange<RangeHalf<T>>
make_half_range(const RangeHalf<T> &a, const RangeHalf<T> &b) {
return HalfRange<RangeHalf<T>>(a, b);
}
} /* namespace octa */

View File

@ -16,9 +16,9 @@
namespace octa {
static constexpr size_t npos = -1;
template<typename _T, typename _A = octa::Allocator<_T>>
template<typename T, typename A = octa::Allocator<T>>
class StringBase {
octa::Vector<_T> p_buf;
octa::Vector<T> p_buf;
void terminate() {
if (p_buf.empty() || (p_buf.back() != '\0')) p_buf.push('\0');
@ -27,56 +27,56 @@ class StringBase {
public:
typedef size_t Size;
typedef ptrdiff_t Difference;
typedef _T Value;
typedef _T &Reference;
typedef const _T &ConstReference;
typedef _T *Pointer;
typedef const _T *ConstPointer;
typedef PointerRange< _T> Range;
typedef PointerRange<const _T> ConstRange;
typedef _A Allocator;
typedef T Value;
typedef T &Reference;
typedef const T &ConstReference;
typedef T *Pointer;
typedef const T *ConstPointer;
typedef PointerRange< T> Range;
typedef PointerRange<const T> ConstRange;
typedef A Allocator;
StringBase(const _A &a = _A()): p_buf(1, '\0', a) {}
StringBase(const A &a = A()): p_buf(1, '\0', a) {}
StringBase(const StringBase &s): p_buf(s.p_buf) {}
StringBase(const StringBase &s, const _A &a):
StringBase(const StringBase &s, const A &a):
p_buf(s.p_buf, a) {}
StringBase(StringBase &&s): p_buf(octa::move(s.p_buf)) {}
StringBase(StringBase &&s, const _A &a):
StringBase(StringBase &&s, const A &a):
p_buf(octa::move(s.p_buf), a) {}
StringBase(const StringBase &s, size_t pos, size_t len = npos,
const _A &a = _A()):
const A &a = A()):
p_buf(s.p_buf.each().slice(pos,
(len == npos) ? s.p_buf.size() : (pos + len)), a) {
terminate();
}
/* TODO: traits for utf-16/utf-32 string lengths, for now assume char */
StringBase(const _T *v, const _A &a = _A()):
StringBase(const T *v, const A &a = A()):
p_buf(ConstRange(v, strlen(v) + 1), a) {}
template<typename _R> StringBase(_R range, const _A &a = _A()):
template<typename R> StringBase(R range, const A &a = A()):
p_buf(range, a) {
terminate();
}
void clear() { p_buf.clear(); }
StringBase<_T> &operator=(const StringBase &v) {
StringBase<T> &operator=(const StringBase &v) {
p_buf.operator=(v);
return *this;
}
StringBase<_T> &operator=(StringBase &&v) {
StringBase<T> &operator=(StringBase &&v) {
p_buf.operator=(octa::move(v));
return *this;
}
StringBase<_T> &operator=(const _T *v) {
StringBase<T> &operator=(const T *v) {
p_buf = ConstRange(v, strlen(v) + 1);
return *this;
}
void resize(size_t n, _T v = _T()) {
void resize(size_t n, T v = T()) {
p_buf.pop();
p_buf.resize(n, v);
terminate();
@ -86,20 +86,20 @@ public:
p_buf.reserve(n + 1);
}
_T &operator[](size_t i) { return p_buf[i]; }
const _T &operator[](size_t i) const { return p_buf[i]; }
T &operator[](size_t i) { return p_buf[i]; }
const T &operator[](size_t i) const { return p_buf[i]; }
_T &at(size_t i) { return p_buf[i]; }
const _T &at(size_t i) const { return p_buf[i]; }
T &at(size_t i) { return p_buf[i]; }
const T &at(size_t i) const { return p_buf[i]; }
_T &front() { return p_buf[0]; }
const _T &front() const { return p_buf[0]; };
T &front() { return p_buf[0]; }
const T &front() const { return p_buf[0]; };
_T &back() { return p_buf[size() - 1]; }
const _T &back() const { return p_buf[size() - 1]; }
T &back() { return p_buf[size() - 1]; }
const T &back() const { return p_buf[size() - 1]; }
_T *data() { return p_buf.data(); }
const _T *data() const { return p_buf.data(); }
T *data() { return p_buf.data(); }
const T *data() const { return p_buf.data(); }
size_t size() const {
return p_buf.size() - 1;
@ -111,54 +111,54 @@ public:
bool empty() const { return (size() == 0); }
void push(_T v) {
void push(T v) {
p_buf.back() = v;
p_buf.push('\0');
}
StringBase<_T> &append(const StringBase &s) {
StringBase<T> &append(const StringBase &s) {
p_buf.pop();
p_buf.insert_range(p_buf.size(), s.p_buf.each());
return *this;
}
StringBase<_T> &append(const StringBase &s, size_t idx, size_t len) {
StringBase<T> &append(const StringBase &s, size_t idx, size_t len) {
p_buf.pop();
p_buf.insert_range(p_buf.size(), octa::PointerRange<_T>(&s[idx],
p_buf.insert_range(p_buf.size(), octa::PointerRange<T>(&s[idx],
(len == npos) ? (s.size() - idx) : len));
terminate();
return *this;
}
StringBase<_T> &append(const _T *s) {
StringBase<T> &append(const T *s) {
p_buf.pop();
p_buf.insert_range(p_buf.size(), ConstRange(s,
strlen(s) + 1));
return *this;
}
StringBase<_T> &append(size_t n, _T c) {
StringBase<T> &append(size_t n, T c) {
p_buf.pop();
for (size_t i = 0; i < n; ++i) p_buf.push(c);
p_buf.push('\0');
return *this;
}
template<typename _R>
StringBase<_T> &append_range(_R range) {
template<typename R>
StringBase<T> &append_range(R range) {
p_buf.pop();
p_buf.insert_range(p_buf.size(), range);
terminate();
return *this;
}
StringBase<_T> &operator+=(const StringBase &s) {
StringBase<T> &operator+=(const StringBase &s) {
return append(s);
}
StringBase<_T> &operator+=(const _T *s) {
StringBase<T> &operator+=(const T *s) {
return append(s);
}
StringBase<_T> &operator+=(_T c) {
StringBase<T> &operator+=(T c) {
p_buf.pop();
p_buf.push(c);
p_buf.push('\0');
@ -179,8 +179,8 @@ public:
typedef StringBase<char> String;
template<typename _T, typename _F>
String concat(const _T v, const String &sep, _F func) {
template<typename T, typename F>
String concat(const T v, const String &sep, F func) {
String ret;
auto range = octa::each(v);
if (range.empty()) return octa::move(ret);
@ -193,8 +193,8 @@ String concat(const _T v, const String &sep, _F func) {
return octa::move(ret);
}
template<typename _T>
String concat(const _T &v, const String &sep = " ") {
template<typename T>
String concat(const T &v, const String &sep = " ") {
String ret;
auto range = octa::each(v);
if (range.empty()) return octa::move(ret);
@ -207,41 +207,41 @@ String concat(const _T &v, const String &sep = " ") {
return octa::move(ret);
}
template<typename _T, typename _F>
String concat(std::initializer_list<_T> v, const String &sep, _F func) {
template<typename T, typename F>
String concat(std::initializer_list<T> v, const String &sep, F func) {
return concat(octa::each(v), sep, func);
}
template<typename _T>
String concat(std::initializer_list<_T> v, const String &sep = " ") {
template<typename T>
String concat(std::initializer_list<T> v, const String &sep = " ") {
return concat(octa::each(v), sep);
}
namespace detail {
template<typename _T>
template<typename T>
struct ToStringTest {
template<typename _U, String (_U::*)() const> struct Test {};
template<typename _U> static char test(Test<_U, &_U::to_string> *);
template<typename _U> static int test(...);
static constexpr bool value = (sizeof(test<_T>(0)) == sizeof(char));
template<typename U, String (U::*)() const> struct Test {};
template<typename U> static char test(Test<U, &U::to_string> *);
template<typename U> static int test(...);
static constexpr bool value = (sizeof(test<T>(0)) == sizeof(char));
};
}
template<typename _T> struct ToString {
typedef _T Argument;
template<typename T> struct ToString {
typedef T Argument;
typedef String Result;
template<typename _U>
static String to_str(const _U &v,
octa::EnableIf<octa::detail::ToStringTest<_U>::value, bool> = true
template<typename U>
static String to_str(const U &v,
octa::EnableIf<octa::detail::ToStringTest<U>::value, bool> = true
) {
return v.to_string();
}
template<typename _U>
static String to_str(const _U &v,
octa::EnableIf<!octa::detail::ToStringTest<_U>::value &&
!octa::IsScalar<_U>::value, bool> = true
template<typename U>
static String to_str(const U &v,
octa::EnableIf<!octa::detail::ToStringTest<U>::value &&
!octa::IsScalar<U>::value, bool> = true
) {
String ret("{");
ret += concat(octa::each(v), ", ", ToString<octa::RangeReference<
@ -251,24 +251,24 @@ template<typename _T> struct ToString {
return octa::move(ret);
}
template<typename _U>
static String to_str(const _U &v,
octa::EnableIf<!octa::detail::ToStringTest<_U>::value &&
octa::IsScalar<_U>::value, bool> = true
template<typename U>
static String to_str(const U &v,
octa::EnableIf<!octa::detail::ToStringTest<U>::value &&
octa::IsScalar<U>::value, bool> = true
) {
return ToString<_U>()(v);
return ToString<U>()(v);
}
String operator()(const _T &v) {
String operator()(const T &v) {
return octa::move(to_str<octa::RemoveCv<
octa::RemoveReference<_T>
octa::RemoveReference<T>
>>(v));
}
};
namespace detail {
template<typename _T>
void str_printf(octa::Vector<char> *s, const char *fmt, _T v) {
template<typename T>
void str_printf(octa::Vector<char> *s, const char *fmt, T v) {
char buf[256];
int n = snprintf(buf, sizeof(buf), fmt, v);
s->clear();
@ -303,11 +303,11 @@ template<> struct ToString<char> {
}
};
#define OCTA_TOSTR_NUM(_T, fmt) \
template<> struct ToString<_T> { \
typedef _T Argument; \
#define OCTA_TOSTR_NUM(T, fmt) \
template<> struct ToString<T> { \
typedef T Argument; \
typedef String Result; \
String operator()(_T v) { \
String operator()(T v) { \
String ret; \
octa::detail::str_printf((octa::Vector<char> *)&ret, fmt, v); \
return octa::move(ret); \
@ -327,8 +327,8 @@ OCTA_TOSTR_NUM(ldouble, "%Lf")
#undef OCTA_TOSTR_NUM
template<typename _T> struct ToString<_T *> {
typedef _T *Argument;
template<typename T> struct ToString<T *> {
typedef T *Argument;
typedef String Result;
String operator()(Argument v) {
String ret;
@ -345,30 +345,30 @@ template<> struct ToString<String> {
}
};
template<typename _T, typename _U> struct ToString<octa::Pair<_T, _U>> {
typedef const octa::Pair<_T, _U> &Argument;
template<typename T, typename U> struct ToString<octa::Pair<T, U>> {
typedef const octa::Pair<T, U> &Argument;
typedef String Result;
String operator()(Argument v) {
String ret("{");
ret += ToString<octa::RemoveCv<octa::RemoveReference<_T>>>()
ret += ToString<octa::RemoveCv<octa::RemoveReference<T>>>()
(v.first);
ret += ", ";
ret += ToString<octa::RemoveCv<octa::RemoveReference<_U>>>()
ret += ToString<octa::RemoveCv<octa::RemoveReference<U>>>()
(v.second);
ret += "}";
return octa::move(ret);
}
};
template<typename _T>
String to_string(const _T &v) {
return octa::move(ToString<octa::RemoveCv<octa::RemoveReference<_T>>>
template<typename T>
String to_string(const T &v) {
return octa::move(ToString<octa::RemoveCv<octa::RemoveReference<T>>>
()(v));
}
template<typename _T>
String to_string(std::initializer_list<_T> init) {
return octa::move(ToString<std::initializer_list<_T>>()(init));
template<typename T>
String to_string(std::initializer_list<T> init) {
return octa::move(ToString<std::initializer_list<T>>()(init));
}
} /* namespace octa */

File diff suppressed because it is too large Load Diff

View File

@ -14,78 +14,78 @@ namespace octa {
/* move */
template<typename _T>
static inline constexpr RemoveReference<_T> &&move(_T &&v) {
return static_cast<RemoveReference<_T> &&>(v);
template<typename T>
static inline constexpr RemoveReference<T> &&move(T &&v) {
return static_cast<RemoveReference<T> &&>(v);
}
/* forward */
template<typename _T>
static inline constexpr _T &&forward(RemoveReference<_T> &v) {
return static_cast<_T &&>(v);
template<typename T>
static inline constexpr T &&forward(RemoveReference<T> &v) {
return static_cast<T &&>(v);
}
template<typename _T>
static inline constexpr _T &&forward(RemoveReference<_T> &&v) {
return static_cast<_T &&>(v);
template<typename T>
static inline constexpr T &&forward(RemoveReference<T> &&v) {
return static_cast<T &&>(v);
}
/* exchange */
template<typename _T, typename _U = _T>
_T exchange(_T &v, _U &&nv) {
_T old = move(v);
v = forward<_U>(nv);
template<typename T, typename U = T>
T exchange(T &v, U &&nv) {
T old = move(v);
v = forward<U>(nv);
return old;
}
/* declval */
template<typename _T> AddRvalueReference<_T> declval();
template<typename T> AddRvalueReference<T> declval();
/* swap */
namespace detail {
template<typename _T>
template<typename T>
struct SwapTest {
template<typename _U, void (_U::*)(_U &)> struct Test {};
template<typename _U> static char test(Test<_U, &_U::swap> *);
template<typename _U> static int test(...);
static constexpr bool value = (sizeof(test<_T>(0)) == sizeof(char));
template<typename U, void (U::*)(U &)> struct Test {};
template<typename U> static char test(Test<U, &U::swap> *);
template<typename U> static int test(...);
static constexpr bool value = (sizeof(test<T>(0)) == sizeof(char));
};
template<typename _T> inline void swap(_T &a, _T &b, EnableIf<
octa::detail::SwapTest<_T>::value, bool
template<typename T> inline void swap(T &a, T &b, EnableIf<
octa::detail::SwapTest<T>::value, bool
> = true) {
a.swap(b);
}
template<typename _T> inline void swap(_T &a, _T &b, EnableIf<
!octa::detail::SwapTest<_T>::value, bool
template<typename T> inline void swap(T &a, T &b, EnableIf<
!octa::detail::SwapTest<T>::value, bool
> = true) {
_T c(octa::move(a));
T c(octa::move(a));
a = octa::move(b);
b = octa::move(c);
}
}
template<typename _T> void swap(_T &a, _T &b) {
template<typename T> void swap(T &a, T &b) {
octa::detail::swap(a, b);
}
template<typename _T, size_t _N> void swap(_T (&a)[_N], _T (&b)[_N]) {
for (size_t i = 0; i < _N; ++i) {
template<typename T, size_t N> void swap(T (&a)[N], T (&b)[N]) {
for (size_t i = 0; i < N; ++i) {
octa::swap(a[i], b[i]);
}
}
/* pair */
template<typename _T, typename _U>
template<typename T, typename U>
struct Pair {
_T first;
_U second;
T first;
U second;
Pair() = default;
~Pair() = default;
@ -93,17 +93,17 @@ struct Pair {
Pair(const Pair &) = default;
Pair(Pair &&) = default;
Pair(const _T &x, const _U &y): first(x), second(y) {}
Pair(const T &x, const U &y): first(x), second(y) {}
template<typename _TT, typename _UU>
Pair(_TT &&x, _UU &&y):
first(octa::forward<_TT>(x)), second(octa::forward<_UU>(y)) {}
template<typename TT, typename UU>
Pair(TT &&x, UU &&y):
first(octa::forward<TT>(x)), second(octa::forward<UU>(y)) {}
template<typename _TT, typename _UU>
Pair(const Pair<_TT, _UU> &v): first(v.first), second(v.second) {}
template<typename TT, typename UU>
Pair(const Pair<TT, UU> &v): first(v.first), second(v.second) {}
template<typename _TT, typename _UU>
Pair(Pair<_TT, _UU> &&v):
template<typename TT, typename UU>
Pair(Pair<TT, UU> &&v):
first(octa::move(v.first)), second(octa::move(v.second)) {}
Pair &operator=(const Pair &v) {
@ -112,8 +112,8 @@ struct Pair {
return *this;
}
template<typename _TT, typename _UU>
Pair &operator=(const Pair<_TT, _UU> &v) {
template<typename TT, typename UU>
Pair &operator=(const Pair<TT, UU> &v) {
first = v.first;
second = v.second;
return *this;
@ -125,10 +125,10 @@ struct Pair {
return *this;
}
template<typename _TT, typename _UU>
Pair &operator=(Pair<_TT, _UU> &&v) {
first = octa::forward<_TT>(v.first);
second = octa::forward<_UU>(v.second);
template<typename TT, typename UU>
Pair &operator=(Pair<TT, UU> &&v) {
first = octa::forward<TT>(v.first);
second = octa::forward<UU>(v.second);
return *this;
}
@ -138,32 +138,32 @@ struct Pair {
}
};
template<typename _T> struct ReferenceWrapper;
template<typename T> struct ReferenceWrapper;
namespace detail {
template<typename _T>
template<typename T>
struct MakePairRetBase {
typedef _T Type;
typedef T Type;
};
template<typename _T>
struct MakePairRetBase<ReferenceWrapper<_T>> {
typedef _T &Type;
template<typename T>
struct MakePairRetBase<ReferenceWrapper<T>> {
typedef T &Type;
};
template<typename _T>
template<typename T>
struct MakePairRet {
typedef typename octa::detail::MakePairRetBase<octa::Decay<_T>>::Type Type;
typedef typename octa::detail::MakePairRetBase<octa::Decay<T>>::Type Type;
};
} /* namespace detail */
template<typename _T, typename _U>
Pair<typename octa::detail::MakePairRet<_T>::Type,
typename octa::detail::MakePairRet<_U>::Type
> make_pair(_T &&a, _U &&b) {
return Pair<typename octa::detail::MakePairRet<_T>::Type,
typename octa::detail::MakePairRet<_U>::Type
>(forward<_T>(a), forward<_U>(b));;
template<typename T, typename U>
Pair<typename octa::detail::MakePairRet<T>::Type,
typename octa::detail::MakePairRet<U>::Type
> make_pair(T &&a, U &&b) {
return Pair<typename octa::detail::MakePairRet<T>::Type,
typename octa::detail::MakePairRet<U>::Type
>(forward<T>(a), forward<U>(b));;
}
} /* namespace octa */

View File

@ -19,20 +19,20 @@
namespace octa {
namespace detail {
template<typename _T, typename _A, bool = octa::IsEmpty<_A>::value>
template<typename T, typename A, bool = octa::IsEmpty<A>::value>
struct VectorPair;
template<typename _T, typename _A>
struct VectorPair<_T, _A, false> { /* non-empty allocator */
_T *p_ptr;
_A p_a;
template<typename T, typename A>
struct VectorPair<T, A, false> { /* non-empty allocator */
T *p_ptr;
A p_a;
template<typename _U>
VectorPair(_T *ptr, _U &&a): p_ptr(ptr),
p_a(octa::forward<_U>(a)) {}
template<typename U>
VectorPair(T *ptr, U &&a): p_ptr(ptr),
p_a(octa::forward<U>(a)) {}
_A &get_alloc() { return p_a; }
const _A &get_alloc() const { return p_a; }
A &get_alloc() { return p_a; }
const A &get_alloc() const { return p_a; }
void swap(VectorPair &v) {
octa::swap(p_ptr, v.p_ptr);
@ -40,16 +40,16 @@ namespace detail {
}
};
template<typename _T, typename _A>
struct VectorPair<_T, _A, true>: _A { /* empty allocator */
_T *p_ptr;
template<typename T, typename A>
struct VectorPair<T, A, true>: A { /* empty allocator */
T *p_ptr;
template<typename _U>
VectorPair(_T *ptr, _U &&a):
_A(octa::forward<_U>(a)), p_ptr(ptr) {}
template<typename U>
VectorPair(T *ptr, U &&a):
A(octa::forward<U>(a)), p_ptr(ptr) {}
_A &get_alloc() { return *this; }
const _A &get_alloc() const { return *this; }
A &get_alloc() { return *this; }
const A &get_alloc() const { return *this; }
void swap(VectorPair &v) {
octa::swap(p_ptr, v.p_ptr);
@ -57,9 +57,9 @@ namespace detail {
};
} /* namespace detail */
template<typename _T, typename _A = octa::Allocator<_T>>
template<typename T, typename A = octa::Allocator<T>>
class Vector {
typedef octa::detail::VectorPair<_T, _A> _vp_type;
typedef octa::detail::VectorPair<T, A> _vp_type;
_vp_type p_buf;
size_t p_len, p_cap;
@ -72,11 +72,11 @@ class Vector {
}
}
template<typename _R>
void ctor_from_range(_R &range, octa::EnableIf<
octa::IsFiniteRandomAccessRange<_R>::value, bool
template<typename R>
void ctor_from_range(R &range, octa::EnableIf<
octa::IsFiniteRandomAccessRange<R>::value, bool
> = true) {
octa::RangeSize<_R> l = range.size();
octa::RangeSize<R> l = range.size();
reserve(l);
p_len = l;
for (size_t i = 0; !range.empty(); range.pop_front()) {
@ -86,9 +86,9 @@ class Vector {
}
}
template<typename _R>
void ctor_from_range(_R &range, EnableIf<
!octa::IsFiniteRandomAccessRange<_R>::value, bool
template<typename R>
void ctor_from_range(R &range, EnableIf<
!octa::IsFiniteRandomAccessRange<R>::value, bool
> = true) {
size_t i = 0;
for (; !range.empty(); range.pop_front()) {
@ -101,11 +101,11 @@ class Vector {
}
void copy_contents(const Vector &v) {
if (octa::IsPod<_T>()) {
memcpy(p_buf.p_ptr, v.p_buf.p_ptr, p_len * sizeof(_T));
if (octa::IsPod<T>()) {
memcpy(p_buf.p_ptr, v.p_buf.p_ptr, p_len * sizeof(T));
} else {
_T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + p_len;
_T *vbuf = v.p_buf.p_ptr;
T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + p_len;
T *vbuf = v.p_buf.p_ptr;
while (cur != last) {
octa::allocator_construct(p_buf.get_alloc(),
cur++, *vbuf++);
@ -116,24 +116,24 @@ class Vector {
public:
enum { MIN_SIZE = 8 };
typedef size_t Size;
typedef ptrdiff_t Difference;
typedef _T Value;
typedef _T &Reference;
typedef const _T &ConstReference;
typedef _T *Pointer;
typedef const _T *ConstPointer;
typedef PointerRange< _T> Range;
typedef PointerRange<const _T> ConstRange;
typedef _A Allocator;
typedef size_t Size;
typedef ptrdiff_t Difference;
typedef T Value;
typedef T &Reference;
typedef const T &ConstReference;
typedef T *Pointer;
typedef const T *ConstPointer;
typedef PointerRange< T> Range;
typedef PointerRange<const T> ConstRange;
typedef A Allocator;
Vector(const _A &a = _A()): p_buf(nullptr, a), p_len(0), p_cap(0) {}
Vector(const A &a = A()): p_buf(nullptr, a), p_len(0), p_cap(0) {}
explicit Vector(size_t n, const _T &val = _T(),
const _A &al = _A()): Vector(al) {
explicit Vector(size_t n, const T &val = T(),
const A &al = A()): Vector(al) {
p_buf.p_ptr = octa::allocator_allocate(p_buf.get_alloc(), n);
p_len = p_cap = n;
_T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + n;
T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + n;
while (cur != last)
octa::allocator_construct(p_buf.get_alloc(), cur++, val);
}
@ -146,7 +146,7 @@ public:
copy_contents(v);
}
Vector(const Vector &v, const _A &a): p_buf(nullptr, a),
Vector(const Vector &v, const A &a): p_buf(nullptr, a),
p_len(0), p_cap(0) {
reserve(v.p_cap);
p_len = v.p_len;
@ -159,16 +159,16 @@ public:
v.p_len = v.p_cap = 0;
}
Vector(Vector &&v, const _A &a) {
Vector(Vector &&v, const A &a) {
if (a != v.a) {
p_buf.get_alloc() = a;
reserve(v.p_cap);
p_len = v.p_len;
if (octa::IsPod<_T>()) {
memcpy(p_buf.p_ptr, v.p_buf.p_ptr, p_len * sizeof(_T));
if (octa::IsPod<T>()) {
memcpy(p_buf.p_ptr, v.p_buf.p_ptr, p_len * sizeof(T));
} else {
_T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + p_len;
_T *vbuf = v.p_buf.p_ptr;
T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + p_len;
T *vbuf = v.p_buf.p_ptr;
while (cur != last) {
octa::allocator_construct(p_buf.get_alloc(), cur++,
octa::move(*vbuf++));
@ -184,9 +184,9 @@ public:
v.p_len = v.p_cap = 0;
}
Vector(InitializerList<_T> v, const _A &a = _A()): Vector(a) {
Vector(InitializerList<T> v, const A &a = A()): Vector(a) {
size_t l = v.end() - v.begin();
const _T *ptr = v.begin();
const T *ptr = v.begin();
reserve(l);
for (size_t i = 0; i < l; ++i)
octa::allocator_construct(p_buf.get_alloc(),
@ -194,7 +194,7 @@ public:
p_len = l;
}
template<typename _R> Vector(_R range, const _A &a = _A()):
template<typename R> Vector(R range, const A &a = A()):
Vector(a) {
ctor_from_range(range);
}
@ -205,8 +205,8 @@ public:
}
void clear() {
if (p_len > 0 && !octa::IsPod<_T>()) {
_T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + p_len;
if (p_len > 0 && !octa::IsPod<T>()) {
T *cur = p_buf.p_ptr, *last = p_buf.p_ptr + p_len;
while (cur != last)
octa::allocator_destroy(p_buf.get_alloc(), cur++);
}
@ -232,14 +232,14 @@ public:
return *this;
}
Vector &operator=(InitializerList<_T> il) {
Vector &operator=(InitializerList<T> il) {
clear();
size_t ilen = il.end() - il.begin();
reserve(ilen);
if (octa::IsPod<_T>()) {
if (octa::IsPod<T>()) {
memcpy(p_buf.p_ptr, il.begin(), ilen);
} else {
_T *tbuf = p_buf.p_ptr, *ibuf = il.begin(),
T *tbuf = p_buf.p_ptr, *ibuf = il.begin(),
*last = il.end();
while (ibuf != last) {
octa::allocator_construct(p_buf.get_alloc(),
@ -250,23 +250,23 @@ public:
return *this;
}
template<typename _R>
Vector &operator=(_R range) {
template<typename R>
Vector &operator=(R range) {
clear();
ctor_from_range(range);
}
void resize(size_t n, const _T &v = _T()) {
void resize(size_t n, const T &v = T()) {
size_t l = p_len;
reserve(n);
p_len = n;
if (octa::IsPod<_T>()) {
if (octa::IsPod<T>()) {
for (size_t i = l; i < p_len; ++i) {
p_buf.p_ptr[i] = _T(v);
p_buf.p_ptr[i] = T(v);
}
} else {
_T *first = p_buf.p_ptr + l;
_T *last = p_buf.p_ptr + p_len;
T *first = p_buf.p_ptr + l;
T *last = p_buf.p_ptr + p_len;
while (first != last)
octa::allocator_construct(p_buf.get_alloc(), first++, v);
}
@ -280,12 +280,12 @@ public:
} else {
while (p_cap < n) p_cap *= 2;
}
_T *tmp = octa::allocator_allocate(p_buf.get_alloc(), p_cap);
T *tmp = octa::allocator_allocate(p_buf.get_alloc(), p_cap);
if (oc > 0) {
if (octa::IsPod<_T>()) {
memcpy(tmp, p_buf.p_ptr, p_len * sizeof(_T));
if (octa::IsPod<T>()) {
memcpy(tmp, p_buf.p_ptr, p_len * sizeof(T));
} else {
_T *cur = p_buf.p_ptr, *tcur = tmp,
T *cur = p_buf.p_ptr, *tcur = tmp,
*last = tmp + p_len;
while (tcur != last) {
octa::allocator_construct(p_buf.get_alloc(), tcur++,
@ -299,35 +299,35 @@ public:
p_buf.p_ptr = tmp;
}
_T &operator[](size_t i) { return p_buf.p_ptr[i]; }
const _T &operator[](size_t i) const { return p_buf.p_ptr[i]; }
T &operator[](size_t i) { return p_buf.p_ptr[i]; }
const T &operator[](size_t i) const { return p_buf.p_ptr[i]; }
_T &at(size_t i) { return p_buf.p_ptr[i]; }
const _T &at(size_t i) const { return p_buf.p_ptr[i]; }
T &at(size_t i) { return p_buf.p_ptr[i]; }
const T &at(size_t i) const { return p_buf.p_ptr[i]; }
_T &push(const _T &v) {
T &push(const T &v) {
if (p_len == p_cap) reserve(p_len + 1);
octa::allocator_construct(p_buf.get_alloc(),
&p_buf.p_ptr[p_len], v);
return p_buf.p_ptr[p_len++];
}
_T &push() {
T &push() {
if (p_len == p_cap) reserve(p_len + 1);
octa::allocator_construct(p_buf.get_alloc(), &p_buf.p_ptr[p_len]);
return p_buf.p_ptr[p_len++];
}
template<typename ..._U>
_T &emplace_back(_U &&...args) {
template<typename ...U>
T &emplace_back(U &&...args) {
if (p_len == p_cap) reserve(p_len + 1);
octa::allocator_construct(p_buf.get_alloc(), &p_buf.p_ptr[p_len],
octa::forward<_U>(args)...);
octa::forward<U>(args)...);
return p_buf.p_ptr[p_len++];
}
void pop() {
if (!octa::IsPod<_T>()) {
if (!octa::IsPod<T>()) {
octa::allocator_destroy(p_buf.get_alloc(),
&p_buf.p_ptr[--p_len]);
} else {
@ -335,14 +335,14 @@ public:
}
}
_T &front() { return p_buf.p_ptr[0]; }
const _T &front() const { return p_buf.p_ptr[0]; }
T &front() { return p_buf.p_ptr[0]; }
const T &front() const { return p_buf.p_ptr[0]; }
_T &back() { return p_buf.p_ptr[p_len - 1]; }
const _T &back() const { return p_buf.p_ptr[p_len - 1]; }
T &back() { return p_buf.p_ptr[p_len - 1]; }
const T &back() const { return p_buf.p_ptr[p_len - 1]; }
_T *data() { return p_buf.p_ptr; }
const _T *data() const { return p_buf.p_ptr; }
T *data() { return p_buf.p_ptr; }
const T *data() const { return p_buf.p_ptr; }
size_t size() const { return p_len; }
size_t capacity() const { return p_cap; }
@ -351,30 +351,30 @@ public:
bool in_range(size_t idx) { return idx < p_len; }
bool in_range(int idx) { return idx >= 0 && size_t(idx) < p_len; }
bool in_range(const _T *ptr) {
bool in_range(const T *ptr) {
return ptr >= p_buf.p_ptr && ptr < &p_buf.p_ptr[p_len];
}
_T *disown() {
_T *r = p_buf.p_ptr;
T *disown() {
T *r = p_buf.p_ptr;
p_buf.p_ptr = nullptr;
p_len = p_cap = 0;
return r;
}
_T *insert(size_t idx, _T &&v) {
T *insert(size_t idx, T &&v) {
insert_base(idx, 1);
p_buf.p_ptr[idx] = octa::move(v);
return &p_buf.p_ptr[idx];
}
_T *insert(size_t idx, const _T &v) {
T *insert(size_t idx, const T &v) {
insert_base(idx, 1);
p_buf.p_ptr[idx] = v;
return &p_buf.p_ptr[idx];
}
_T *insert(size_t idx, size_t n, const _T &v) {
T *insert(size_t idx, size_t n, const T &v) {
insert_base(idx, n);
for (size_t i = 0; i < n; ++i) {
p_buf.p_ptr[idx + i] = v;
@ -382,8 +382,8 @@ public:
return &p_buf.p_ptr[idx];
}
template<typename _U>
_T *insert_range(size_t idx, _U range) {
template<typename U>
T *insert_range(size_t idx, U range) {
size_t l = range.size();
insert_base(idx, l);
for (size_t i = 0; i < l; ++i) {
@ -393,7 +393,7 @@ public:
return &p_buf.p_ptr[idx];
}
_T *insert(size_t idx, InitializerList<_T> il) {
T *insert(size_t idx, InitializerList<T> il) {
return insert_range(idx, octa::each(il));
}