get rid of namespace internal
parent
cca0a62d34
commit
f106c5ae24
|
@ -12,7 +12,7 @@ go beyond C++11 level when it comes to core language features.
|
||||||
Compiler | Version
|
Compiler | Version
|
||||||
-------- | -------
|
-------- | -------
|
||||||
gcc/g++ | 4.8+
|
gcc/g++ | 4.8+
|
||||||
clang | 3.4+
|
clang | 3.3+
|
||||||
MSVC++ | 2015+
|
MSVC++ | 2015+
|
||||||
|
|
||||||
Other C++11 compliant compilers might work as well. OctaSTD does not utilize
|
Other C++11 compliant compilers might work as well. OctaSTD does not utilize
|
||||||
|
|
136
octa/algorithm.h
136
octa/algorithm.h
|
@ -14,6 +14,8 @@
|
||||||
#include "octa/initializer_list.h"
|
#include "octa/initializer_list.h"
|
||||||
|
|
||||||
namespace octa {
|
namespace octa {
|
||||||
|
/* partitioning */
|
||||||
|
|
||||||
template<typename R, typename U>
|
template<typename R, typename U>
|
||||||
R partition(R range, U pred) {
|
R partition(R range, U pred) {
|
||||||
R ret = range;
|
R ret = range;
|
||||||
|
@ -34,6 +36,8 @@ namespace octa {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* insertion sort */
|
||||||
|
|
||||||
template<typename R, typename C>
|
template<typename R, typename C>
|
||||||
void insertion_sort(R range, C compare) {
|
void insertion_sort(R range, C compare) {
|
||||||
size_t rlen = range.length();
|
size_t rlen = range.length();
|
||||||
|
@ -52,76 +56,76 @@ namespace octa {
|
||||||
insertion_sort(range, Less<typename RangeTraits<R>::value>());
|
insertion_sort(range, Less<typename RangeTraits<R>::value>());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace internal {
|
/* sort (introsort) */
|
||||||
template<typename T, typename U>
|
|
||||||
struct UnaryCompare {
|
|
||||||
const T &val;
|
|
||||||
U comp;
|
|
||||||
bool operator()(const T &v) const { return comp(v, val); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename R, typename C>
|
template<typename T, typename U>
|
||||||
void hs_sift_down(R range, size_t s, size_t e, C compare) {
|
struct __OctaUnaryCompare {
|
||||||
size_t r = s;
|
const T &val;
|
||||||
while ((r * 2 + 1) <= e) {
|
U comp;
|
||||||
size_t ch = r * 2 + 1;
|
bool operator()(const T &v) const { return comp(v, val); }
|
||||||
size_t sw = r;
|
};
|
||||||
if (compare(range[sw], range[ch]))
|
|
||||||
sw = ch;
|
|
||||||
if (((ch + 1) <= e) && compare(range[sw], range[ch + 1]))
|
|
||||||
sw = ch + 1;
|
|
||||||
if (sw != r) {
|
|
||||||
swap(range[r], range[sw]);
|
|
||||||
r = sw;
|
|
||||||
} else return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename R, typename C>
|
template<typename R, typename C>
|
||||||
void heapsort(R range, C compare) {
|
void __octa_hs_sift_down(R range, size_t s, size_t e, C compare) {
|
||||||
size_t len = range.length();
|
size_t r = s;
|
||||||
size_t st = (len - 2) / 2;
|
while ((r * 2 + 1) <= e) {
|
||||||
for (;;) {
|
size_t ch = r * 2 + 1;
|
||||||
hs_sift_down(range, st, len - 1, compare);
|
size_t sw = r;
|
||||||
if (st-- == 0) break;
|
if (compare(range[sw], range[ch]))
|
||||||
}
|
sw = ch;
|
||||||
size_t e = len - 1;
|
if (((ch + 1) <= e) && compare(range[sw], range[ch + 1]))
|
||||||
while (e > 0) {
|
sw = ch + 1;
|
||||||
swap(range[e], range[0]);
|
if (sw != r) {
|
||||||
--e;
|
swap(range[r], range[sw]);
|
||||||
hs_sift_down(range, 0, e, compare);
|
r = sw;
|
||||||
}
|
} else return;
|
||||||
}
|
|
||||||
|
|
||||||
template<typename R, typename C>
|
|
||||||
void introloop(R range, C compare, size_t depth) {
|
|
||||||
if (range.length() <= 10) {
|
|
||||||
insertion_sort(range, compare);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (depth == 0) {
|
|
||||||
heapsort(range, compare);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
typename RangeTraits<R>::reference p = range[range.length() / 2];
|
|
||||||
swap(p, range.last());
|
|
||||||
R r = partition(range, UnaryCompare<decltype(p), C>{ p, compare });
|
|
||||||
R l = range.slice(0, range.length() - r.length());
|
|
||||||
swap(r.first(), r.last());
|
|
||||||
introloop(l, compare, depth - 1);
|
|
||||||
introloop(r, compare, depth - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename R, typename C>
|
|
||||||
void introsort(R range, C compare) {
|
|
||||||
introloop(range, compare, size_t(2
|
|
||||||
* (log(range.length()) / log(2))));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename R, typename C>
|
||||||
|
void __octa_heapsort(R range, C compare) {
|
||||||
|
size_t len = range.length();
|
||||||
|
size_t st = (len - 2) / 2;
|
||||||
|
for (;;) {
|
||||||
|
__octa_hs_sift_down(range, st, len - 1, compare);
|
||||||
|
if (st-- == 0) break;
|
||||||
|
}
|
||||||
|
size_t e = len - 1;
|
||||||
|
while (e > 0) {
|
||||||
|
swap(range[e], range[0]);
|
||||||
|
--e;
|
||||||
|
__octa_hs_sift_down(range, 0, e, compare);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R, typename C>
|
||||||
|
void __octa_introloop(R range, C compare, size_t depth) {
|
||||||
|
if (range.length() <= 10) {
|
||||||
|
insertion_sort(range, compare);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (depth == 0) {
|
||||||
|
__octa_heapsort(range, compare);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
typename RangeTraits<R>::reference p = range[range.length() / 2];
|
||||||
|
swap(p, range.last());
|
||||||
|
R r = partition(range, __OctaUnaryCompare<decltype(p), C>{ p, compare });
|
||||||
|
R l = range.slice(0, range.length() - r.length());
|
||||||
|
swap(r.first(), r.last());
|
||||||
|
__octa_introloop(l, compare, depth - 1);
|
||||||
|
__octa_introloop(r, compare, depth - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R, typename C>
|
||||||
|
void __octa_introsort(R range, C compare) {
|
||||||
|
__octa_introloop(range, compare, size_t(2
|
||||||
|
* (log(range.length()) / log(2))));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename R, typename C>
|
template<typename R, typename C>
|
||||||
void sort(R range, C compare) {
|
void sort(R range, C compare) {
|
||||||
internal::introsort(range, compare);
|
__octa_introsort(range, compare);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename R>
|
template<typename R>
|
||||||
|
@ -129,6 +133,8 @@ namespace octa {
|
||||||
sort(range, Less<typename RangeTraits<R>::value>());
|
sort(range, Less<typename RangeTraits<R>::value>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* min/max(_element) */
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline const T &min(const T &a, const T &b) {
|
inline const T &min(const T &a, const T &b) {
|
||||||
return (a < b) ? a : b;
|
return (a < b) ? a : b;
|
||||||
|
@ -200,6 +206,8 @@ namespace octa {
|
||||||
return max_element(il.range(), compare).first();
|
return max_element(il.range(), compare).first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* algos that don't change the range */
|
||||||
|
|
||||||
template<typename R, typename F>
|
template<typename R, typename F>
|
||||||
F for_each(R range, F func) {
|
F for_each(R range, F func) {
|
||||||
for (; !range.empty(); range.pop_first())
|
for (; !range.empty(); range.pop_first())
|
||||||
|
@ -289,6 +297,8 @@ namespace octa {
|
||||||
return range2.empty();
|
return range2.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* algos that modify ranges or work with output ranges */
|
||||||
|
|
||||||
template<typename R1, typename R2>
|
template<typename R1, typename R2>
|
||||||
R2 copy(R1 irange, R2 orange) {
|
R2 copy(R1 irange, R2 orange) {
|
||||||
for (; !irange.empty(); irange.pop_first())
|
for (; !irange.empty(); irange.pop_first())
|
||||||
|
|
|
@ -12,7 +12,9 @@
|
||||||
#include "octa/traits.h"
|
#include "octa/traits.h"
|
||||||
|
|
||||||
namespace octa {
|
namespace octa {
|
||||||
#define OCTA_DEFINE_BINARY_OP(name, op, rettype) \
|
/* basic function objects */
|
||||||
|
|
||||||
|
#define __OCTA_DEFINE_BINARY_OP(name, op, rettype) \
|
||||||
template<typename T> struct name { \
|
template<typename T> struct name { \
|
||||||
bool operator()(const T &x, const T &y) const { return x op y; } \
|
bool operator()(const T &x, const T &y) const { return x op y; } \
|
||||||
struct type { \
|
struct type { \
|
||||||
|
@ -22,24 +24,24 @@ namespace octa {
|
||||||
}; \
|
}; \
|
||||||
};
|
};
|
||||||
|
|
||||||
OCTA_DEFINE_BINARY_OP(Less, <, bool)
|
__OCTA_DEFINE_BINARY_OP(Less, <, bool)
|
||||||
OCTA_DEFINE_BINARY_OP(LessEqual, <=, bool)
|
__OCTA_DEFINE_BINARY_OP(LessEqual, <=, bool)
|
||||||
OCTA_DEFINE_BINARY_OP(Greater, >, bool)
|
__OCTA_DEFINE_BINARY_OP(Greater, >, bool)
|
||||||
OCTA_DEFINE_BINARY_OP(GreaterEqual, >=, bool)
|
__OCTA_DEFINE_BINARY_OP(GreaterEqual, >=, bool)
|
||||||
OCTA_DEFINE_BINARY_OP(Equal, ==, bool)
|
__OCTA_DEFINE_BINARY_OP(Equal, ==, bool)
|
||||||
OCTA_DEFINE_BINARY_OP(NotEqual, !=, bool)
|
__OCTA_DEFINE_BINARY_OP(NotEqual, !=, bool)
|
||||||
OCTA_DEFINE_BINARY_OP(LogicalAnd, &&, bool)
|
__OCTA_DEFINE_BINARY_OP(LogicalAnd, &&, bool)
|
||||||
OCTA_DEFINE_BINARY_OP(LogicalOr, ||, bool)
|
__OCTA_DEFINE_BINARY_OP(LogicalOr, ||, bool)
|
||||||
OCTA_DEFINE_BINARY_OP(Modulus, %, T)
|
__OCTA_DEFINE_BINARY_OP(Modulus, %, T)
|
||||||
OCTA_DEFINE_BINARY_OP(Multiplies, *, T)
|
__OCTA_DEFINE_BINARY_OP(Multiplies, *, T)
|
||||||
OCTA_DEFINE_BINARY_OP(Divides, /, T)
|
__OCTA_DEFINE_BINARY_OP(Divides, /, T)
|
||||||
OCTA_DEFINE_BINARY_OP(Plus, +, T)
|
__OCTA_DEFINE_BINARY_OP(Plus, +, T)
|
||||||
OCTA_DEFINE_BINARY_OP(Minus, -, T)
|
__OCTA_DEFINE_BINARY_OP(Minus, -, T)
|
||||||
OCTA_DEFINE_BINARY_OP(BitAnd, &, T)
|
__OCTA_DEFINE_BINARY_OP(BitAnd, &, T)
|
||||||
OCTA_DEFINE_BINARY_OP(BitOr, |, T)
|
__OCTA_DEFINE_BINARY_OP(BitOr, |, T)
|
||||||
OCTA_DEFINE_BINARY_OP(BitXor, ^, T)
|
__OCTA_DEFINE_BINARY_OP(BitXor, ^, T)
|
||||||
|
|
||||||
#undef OCTA_DEFINE_BINARY_OP
|
#undef __OCTA_DEFINE_BINARY_OP
|
||||||
|
|
||||||
template<typename T> struct LogicalNot {
|
template<typename T> struct LogicalNot {
|
||||||
bool operator()(const T &x) const { return !x; }
|
bool operator()(const T &x) const { return !x; }
|
||||||
|
@ -93,6 +95,8 @@ namespace octa {
|
||||||
return BinaryNegate<T>(fn);
|
return BinaryNegate<T>(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* reference wrapper */
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct ReferenceWrapper {
|
struct ReferenceWrapper {
|
||||||
typedef T type;
|
typedef T type;
|
||||||
|
@ -126,64 +130,64 @@ namespace octa {
|
||||||
}
|
}
|
||||||
template<typename T> void cref(const T &&) = delete;
|
template<typename T> void cref(const T &&) = delete;
|
||||||
|
|
||||||
namespace internal {
|
/* mem_fn */
|
||||||
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 first;
|
|
||||||
typedef A second;
|
|
||||||
};
|
|
||||||
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 first;
|
|
||||||
typedef A second;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename R, typename T>
|
template<typename, typename> struct __OctaMemTypes;
|
||||||
class MemFn {
|
template<typename T, typename R, typename ...A>
|
||||||
R T::*p_ptr;
|
struct __OctaMemTypes<T, R(A...)> {
|
||||||
public:
|
typedef R result;
|
||||||
struct type: MemTypes<T, R> {};
|
typedef T argument;
|
||||||
|
};
|
||||||
MemFn(R T::*ptr): p_ptr(ptr) {}
|
template<typename T, typename R, typename A>
|
||||||
template<typename... A>
|
struct __OctaMemTypes<T, R(A)> {
|
||||||
auto operator()(T &obj, A &&...args) ->
|
typedef R result;
|
||||||
decltype(((obj).*(p_ptr))(forward<A>(args)...)) {
|
typedef T first;
|
||||||
return ((obj).*(p_ptr))(forward<A>(args)...);
|
typedef A second;
|
||||||
}
|
};
|
||||||
template<typename... A>
|
template<typename T, typename R, typename ...A>
|
||||||
auto operator()(const T &obj, A &&...args) ->
|
struct __OctaMemTypes<T, R(A...) const> {
|
||||||
decltype(((obj).*(p_ptr))(forward<A>(args)...)) const {
|
typedef R result;
|
||||||
return ((obj).*(p_ptr))(forward<A>(args)...);
|
typedef const T argument;
|
||||||
}
|
};
|
||||||
template<typename... A>
|
template<typename T, typename R, typename A>
|
||||||
auto operator()(T *obj, A &&...args) ->
|
struct __OctaMemTypes<T, R(A) const> {
|
||||||
decltype(((obj)->*(p_ptr))(forward<A>(args)...)) {
|
typedef R result;
|
||||||
return ((obj)->*(p_ptr))(forward<A>(args)...);
|
typedef const T first;
|
||||||
}
|
typedef A second;
|
||||||
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 R, typename T>
|
template<typename R, typename T>
|
||||||
internal::MemFn<R, T> mem_fn(R T:: *ptr) {
|
class __OctaMemFn {
|
||||||
return internal::MemFn<R, T>(ptr);
|
R T::*p_ptr;
|
||||||
|
public:
|
||||||
|
struct type: __OctaMemTypes<T, R> {};
|
||||||
|
|
||||||
|
__OctaMemFn(R T::*ptr): p_ptr(ptr) {}
|
||||||
|
template<typename... A>
|
||||||
|
auto operator()(T &obj, A &&...args) ->
|
||||||
|
decltype(((obj).*(p_ptr))(forward<A>(args)...)) {
|
||||||
|
return ((obj).*(p_ptr))(forward<A>(args)...);
|
||||||
|
}
|
||||||
|
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()(const T *obj, A &&...args) ->
|
||||||
|
decltype(((obj)->*(p_ptr))(forward<A>(args)...)) const {
|
||||||
|
return ((obj)->*(p_ptr))(forward<A>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename R, typename T>
|
||||||
|
__OctaMemFn<R, T> mem_fn(R T:: *ptr) {
|
||||||
|
return __OctaMemFn<R, T>(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* function impl
|
/* function impl
|
||||||
|
@ -192,158 +196,161 @@ namespace octa {
|
||||||
|
|
||||||
template<typename> struct Function;
|
template<typename> struct Function;
|
||||||
|
|
||||||
namespace internal {
|
struct __OctaFunctorData {
|
||||||
struct FunctorData {
|
void *p1, *p2;
|
||||||
void *p1, *p2;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct FunctorInPlace {
|
struct __OctaFunctorInPlace {
|
||||||
static constexpr bool value = sizeof(T) <= sizeof(FunctorData)
|
static constexpr bool value = sizeof(T) <= sizeof(__OctaFunctorData)
|
||||||
&& (alignof(FunctorData) % alignof(T)) == 0
|
&& (alignof(__OctaFunctorData) % alignof(T)) == 0
|
||||||
&& octa::IsNothrowMoveConstructible<T>::value;
|
&& octa::IsNothrowMoveConstructible<T>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename E = void>
|
template<typename T, typename E = void>
|
||||||
struct FunctorDataManager {
|
struct __OctaFunctorDataManager {
|
||||||
template<typename R, typename ...A>
|
template<typename R, typename ...A>
|
||||||
static R call(const FunctorData &s, A ...args) {
|
static R call(const __OctaFunctorData &s, A ...args) {
|
||||||
return ((T &)s)(forward<A>(args)...);
|
return ((T &)s)(forward<A>(args)...);
|
||||||
}
|
|
||||||
|
|
||||||
static void store_f(FunctorData &s, T v) {
|
|
||||||
new (&get_ref(s)) T(forward<T>(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void move_f(FunctorData &lhs, FunctorData &&rhs) {
|
|
||||||
new (&get_ref(lhs)) T(move(get_ref(rhs)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroy_f(FunctorData &s) {
|
|
||||||
get_ref(s).~T();
|
|
||||||
}
|
|
||||||
|
|
||||||
static T &get_ref(const FunctorData &s) {
|
|
||||||
return (T &)s;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct FunctorDataManager<T, typename EnableIf<!FunctorInPlace<T>
|
|
||||||
::value>::type> {
|
|
||||||
template<typename R, typename ...A>
|
|
||||||
static R call(const FunctorData &s, A ...args) {
|
|
||||||
return (*(T *&)s)(forward<A>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void store_f(FunctorData &s, T v) {
|
|
||||||
new (&get_ptr_ref(s)) T *(new T(forward<T>(v)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void move_f(FunctorData &lhs, FunctorData &&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);
|
|
||||||
if (!ptr) return;
|
|
||||||
delete ptr;
|
|
||||||
ptr = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
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(const FunctorData &s) {
|
|
||||||
return (T *&)s;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FunctionManager;
|
|
||||||
|
|
||||||
struct ManagerStorage {
|
|
||||||
FunctorData data;
|
|
||||||
const FunctionManager *manager;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static const FunctionManager &get_default_manager();
|
|
||||||
|
|
||||||
struct FunctionManager {
|
|
||||||
template<typename T>
|
|
||||||
inline static const FunctionManager create_default_manager() {
|
|
||||||
return FunctionManager {
|
|
||||||
&t_call_move_and_destroy<T>,
|
|
||||||
&t_call_copy<T>,
|
|
||||||
&t_call_destroy<T>
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void (* const call_move_and_destroy)(ManagerStorage &lhs, ManagerStorage &&rhs);
|
|
||||||
void (* const call_copy)(ManagerStorage &lhs, const ManagerStorage &rhs);
|
|
||||||
void (* const call_destroy)(ManagerStorage &s);
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static void t_call_move_and_destroy(ManagerStorage &lhs, ManagerStorage &&rhs) {
|
|
||||||
typedef FunctorDataManager<T> spec;
|
|
||||||
spec::move_f(lhs.data, move(rhs.data));
|
|
||||||
spec::destroy_f(rhs.data);
|
|
||||||
lhs.manager = &get_default_manager<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static void t_call_copy(ManagerStorage &lhs, const ManagerStorage &rhs) {
|
|
||||||
typedef FunctorDataManager<T> spec;
|
|
||||||
lhs.manager = &get_default_manager<T>();
|
|
||||||
spec::store_f(lhs.data, spec::get_ref(rhs.data));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static void t_call_destroy(ManagerStorage &s) {
|
|
||||||
typedef FunctorDataManager<T> spec;
|
|
||||||
spec::destroy_f(s.data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline static const FunctionManager &get_default_manager() {
|
|
||||||
static const FunctionManager def_manager = FunctionManager::create_default_manager<T>();
|
|
||||||
return def_manager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename R, typename...>
|
static void store_f(__OctaFunctorData &s, T v) {
|
||||||
struct FunctionBase {
|
new (&get_ref(s)) T(forward<T>(v));
|
||||||
struct type {
|
}
|
||||||
typedef R result;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename R, typename T>
|
static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) {
|
||||||
struct FunctionBase<R, T> {
|
new (&get_ref(lhs)) T(move(get_ref(rhs)));
|
||||||
struct type {
|
}
|
||||||
typedef R result;
|
|
||||||
typedef T argument;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename R, typename T, typename U>
|
static void destroy_f(__OctaFunctorData &s) {
|
||||||
struct FunctionBase<R, T, U> {
|
get_ref(s).~T();
|
||||||
struct type {
|
}
|
||||||
typedef R result;
|
|
||||||
typedef T first;
|
static T &get_ref(const __OctaFunctorData &s) {
|
||||||
typedef U second;
|
return (T &)s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct __OctaFunctorDataManager<T, typename EnableIf<!__OctaFunctorInPlace<T>
|
||||||
|
::value>::type> {
|
||||||
|
template<typename R, typename ...A>
|
||||||
|
static R call(const __OctaFunctorData &s, A ...args) {
|
||||||
|
return (*(T *&)s)(forward<A>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void store_f(__OctaFunctorData &s, T v) {
|
||||||
|
new (&get_ptr_ref(s)) T *(new T(forward<T>(v)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) {
|
||||||
|
new (&get_ptr_ref(lhs)) T *(get_ptr_ref(rhs));
|
||||||
|
get_ptr_ref(rhs) = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroy_f(__OctaFunctorData &s) {
|
||||||
|
T *&ptr = get_ptr_ref(s);
|
||||||
|
if (!ptr) return;
|
||||||
|
delete ptr;
|
||||||
|
ptr = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static T &get_ref(const __OctaFunctorData &s) {
|
||||||
|
return *get_ptr_ref(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static T *&get_ptr_ref(__OctaFunctorData &s) {
|
||||||
|
return (T *&)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static T *&get_ptr_ref(const __OctaFunctorData &s) {
|
||||||
|
return (T *&)s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __OctaFunctionManager;
|
||||||
|
|
||||||
|
struct __OctaFMStorage {
|
||||||
|
__OctaFunctorData data;
|
||||||
|
const __OctaFunctionManager *manager;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static const __OctaFunctionManager &__octa_get_default_fm();
|
||||||
|
|
||||||
|
struct __OctaFunctionManager {
|
||||||
|
template<typename T>
|
||||||
|
inline static const __OctaFunctionManager create_default_manager() {
|
||||||
|
return __OctaFunctionManager {
|
||||||
|
&t_call_move_and_destroy<T>,
|
||||||
|
&t_call_copy<T>,
|
||||||
|
&t_call_destroy<T>
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
|
void (* const call_move_and_destroy)(__OctaFMStorage &lhs,
|
||||||
|
__OctaFMStorage &&rhs);
|
||||||
|
void (* const call_copy)(__OctaFMStorage &lhs,
|
||||||
|
const __OctaFMStorage &rhs);
|
||||||
|
void (* const call_destroy)(__OctaFMStorage &s);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static void t_call_move_and_destroy(__OctaFMStorage &lhs,
|
||||||
|
__OctaFMStorage &&rhs) {
|
||||||
|
typedef __OctaFunctorDataManager<T> spec;
|
||||||
|
spec::move_f(lhs.data, move(rhs.data));
|
||||||
|
spec::destroy_f(rhs.data);
|
||||||
|
lhs.manager = &__octa_get_default_fm<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static void t_call_copy(__OctaFMStorage &lhs,
|
||||||
|
const __OctaFMStorage &rhs) {
|
||||||
|
typedef __OctaFunctorDataManager<T> spec;
|
||||||
|
lhs.manager = &__octa_get_default_fm<T>();
|
||||||
|
spec::store_f(lhs.data, spec::get_ref(rhs.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static void t_call_destroy(__OctaFMStorage &s) {
|
||||||
|
typedef __OctaFunctorDataManager<T> spec;
|
||||||
|
spec::destroy_f(s.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline static const __OctaFunctionManager &__octa_get_default_fm() {
|
||||||
|
static const __OctaFunctionManager def_manager
|
||||||
|
= __OctaFunctionManager::create_default_manager<T>();
|
||||||
|
return def_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename R, typename...>
|
||||||
|
struct __OctaFunction {
|
||||||
|
struct type {
|
||||||
|
typedef R result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename R, typename T>
|
||||||
|
struct __OctaFunction<R, T> {
|
||||||
|
struct type {
|
||||||
|
typedef R result;
|
||||||
|
typedef T argument;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename R, typename T, typename U>
|
||||||
|
struct __OctaFunction<R, T, U> {
|
||||||
|
struct type {
|
||||||
|
typedef R result;
|
||||||
|
typedef T first;
|
||||||
|
typedef U second;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
template<typename R, typename ...A>
|
template<typename R, typename ...A>
|
||||||
struct Function<R(A...)>: internal::FunctionBase<R, A...> {
|
struct Function<R(A...)>: __OctaFunction<R, A...> {
|
||||||
Function( ) { initialize_empty(); }
|
Function( ) { initialize_empty(); }
|
||||||
Function(nullptr_t) { initialize_empty(); }
|
Function(nullptr_t) { initialize_empty(); }
|
||||||
|
|
||||||
|
@ -391,7 +398,7 @@ namespace octa {
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(Function &f) {
|
void swap(Function &f) {
|
||||||
internal::ManagerStorage tmp;
|
__OctaFMStorage tmp;
|
||||||
f.p_stor.manager->call_move_and_destroy(tmp, move(f.p_stor));
|
f.p_stor.manager->call_move_and_destroy(tmp, move(f.p_stor));
|
||||||
p_stor.manager->call_move_and_destroy(f.p_stor, move(p_stor));
|
p_stor.manager->call_move_and_destroy(f.p_stor, move(p_stor));
|
||||||
tmp.manager->call_move_and_destroy(p_stor, move(tmp));
|
tmp.manager->call_move_and_destroy(p_stor, move(tmp));
|
||||||
|
@ -401,21 +408,21 @@ namespace octa {
|
||||||
operator bool() const { return p_call != nullptr; }
|
operator bool() const { return p_call != nullptr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
internal::ManagerStorage p_stor;
|
__OctaFMStorage p_stor;
|
||||||
R (*p_call)(const internal::FunctorData &, A...);
|
R (*p_call)(const __OctaFunctorData &, A...);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void initialize(T f) {
|
void initialize(T f) {
|
||||||
p_call = &internal::FunctorDataManager<T>::template call<R, A...>;
|
p_call = &__OctaFunctorDataManager<T>::template call<R, A...>;
|
||||||
p_stor.manager = &internal::get_default_manager<T>();
|
p_stor.manager = &__octa_get_default_fm<T>();
|
||||||
internal::FunctorDataManager<T>::store_f(p_stor.data, forward<T>(f));
|
__OctaFunctorDataManager<T>::store_f(p_stor.data, forward<T>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize_empty() {
|
void initialize_empty() {
|
||||||
typedef R(*emptyf)(A...);
|
typedef R(*emptyf)(A...);
|
||||||
p_call = nullptr;
|
p_call = nullptr;
|
||||||
p_stor.manager = &internal::get_default_manager<emptyf>();
|
p_stor.manager = &__octa_get_default_fm<emptyf>();
|
||||||
internal::FunctorDataManager<emptyf>::store_f(p_stor.data, nullptr);
|
__OctaFunctorDataManager<emptyf>::store_f(p_stor.data, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
46
octa/range.h
46
octa/range.h
|
@ -25,26 +25,24 @@ namespace octa {
|
||||||
typedef typename T::type::reference reference;
|
typedef typename T::type::reference reference;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
template<typename T>
|
||||||
template<typename T>
|
struct __OctaRangeIterator {
|
||||||
struct RangeIterator {
|
__OctaRangeIterator(): p_range() {}
|
||||||
RangeIterator(): p_range() {}
|
explicit __OctaRangeIterator(const T &range): p_range(range) {}
|
||||||
explicit RangeIterator(const T &range): p_range(range) {}
|
__OctaRangeIterator &operator++() {
|
||||||
RangeIterator &operator++() {
|
p_range.pop_first();
|
||||||
p_range.pop_first();
|
return *this;
|
||||||
return *this;
|
}
|
||||||
}
|
typename RangeTraits<T>::reference operator*() {
|
||||||
typename RangeTraits<T>::reference operator*() {
|
return p_range.first();
|
||||||
return p_range.first();
|
}
|
||||||
}
|
typename RangeTraits<T>::reference operator*() const {
|
||||||
typename RangeTraits<T>::reference operator*() const {
|
return p_range.first();
|
||||||
return p_range.first();
|
}
|
||||||
}
|
bool operator!=(__OctaRangeIterator) const { return !p_range.empty(); }
|
||||||
bool operator!=(RangeIterator) const { return !p_range.empty(); }
|
private:
|
||||||
private:
|
T p_range;
|
||||||
T p_range;
|
};
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename B, typename C, typename V, typename R = V &>
|
template<typename B, typename C, typename V, typename R = V &>
|
||||||
struct InputRangeBase {
|
struct InputRangeBase {
|
||||||
|
@ -54,11 +52,11 @@ namespace octa {
|
||||||
typedef R reference;
|
typedef R reference;
|
||||||
};
|
};
|
||||||
|
|
||||||
internal::RangeIterator<B> begin() {
|
__OctaRangeIterator<B> begin() {
|
||||||
return internal::RangeIterator<B>((const B &)*this);
|
return __OctaRangeIterator<B>((const B &)*this);
|
||||||
}
|
}
|
||||||
internal::RangeIterator<B> end() {
|
__OctaRangeIterator<B> end() {
|
||||||
return internal::RangeIterator<B>();
|
return __OctaRangeIterator<B>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue