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
|
||||
-------- | -------
|
||||
gcc/g++ | 4.8+
|
||||
clang | 3.4+
|
||||
clang | 3.3+
|
||||
MSVC++ | 2015+
|
||||
|
||||
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"
|
||||
|
||||
namespace octa {
|
||||
/* partitioning */
|
||||
|
||||
template<typename R, typename U>
|
||||
R partition(R range, U pred) {
|
||||
R ret = range;
|
||||
|
@ -34,6 +36,8 @@ namespace octa {
|
|||
return true;
|
||||
}
|
||||
|
||||
/* insertion sort */
|
||||
|
||||
template<typename R, typename C>
|
||||
void insertion_sort(R range, C compare) {
|
||||
size_t rlen = range.length();
|
||||
|
@ -52,76 +56,76 @@ namespace octa {
|
|||
insertion_sort(range, Less<typename RangeTraits<R>::value>());
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
template<typename T, typename U>
|
||||
struct UnaryCompare {
|
||||
const T &val;
|
||||
U comp;
|
||||
bool operator()(const T &v) const { return comp(v, val); }
|
||||
};
|
||||
/* sort (introsort) */
|
||||
|
||||
template<typename R, typename C>
|
||||
void hs_sift_down(R range, size_t s, size_t e, C compare) {
|
||||
size_t r = s;
|
||||
while ((r * 2 + 1) <= e) {
|
||||
size_t ch = r * 2 + 1;
|
||||
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 T, typename U>
|
||||
struct __OctaUnaryCompare {
|
||||
const T &val;
|
||||
U comp;
|
||||
bool operator()(const T &v) const { return comp(v, val); }
|
||||
};
|
||||
|
||||
template<typename R, typename C>
|
||||
void heapsort(R range, C compare) {
|
||||
size_t len = range.length();
|
||||
size_t st = (len - 2) / 2;
|
||||
for (;;) {
|
||||
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;
|
||||
hs_sift_down(range, 0, e, compare);
|
||||
}
|
||||
}
|
||||
|
||||
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_hs_sift_down(R range, size_t s, size_t e, C compare) {
|
||||
size_t r = s;
|
||||
while ((r * 2 + 1) <= e) {
|
||||
size_t ch = r * 2 + 1;
|
||||
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>
|
||||
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>
|
||||
void sort(R range, C compare) {
|
||||
internal::introsort(range, compare);
|
||||
__octa_introsort(range, compare);
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
|
@ -129,6 +133,8 @@ namespace octa {
|
|||
sort(range, Less<typename RangeTraits<R>::value>());
|
||||
}
|
||||
|
||||
/* min/max(_element) */
|
||||
|
||||
template<typename T>
|
||||
inline const T &min(const T &a, const T &b) {
|
||||
return (a < b) ? a : b;
|
||||
|
@ -200,6 +206,8 @@ namespace octa {
|
|||
return max_element(il.range(), compare).first();
|
||||
}
|
||||
|
||||
/* algos that don't change the range */
|
||||
|
||||
template<typename R, typename F>
|
||||
F for_each(R range, F func) {
|
||||
for (; !range.empty(); range.pop_first())
|
||||
|
@ -289,6 +297,8 @@ namespace octa {
|
|||
return range2.empty();
|
||||
}
|
||||
|
||||
/* algos that modify ranges or work with output ranges */
|
||||
|
||||
template<typename R1, typename R2>
|
||||
R2 copy(R1 irange, R2 orange) {
|
||||
for (; !irange.empty(); irange.pop_first())
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
#include "octa/traits.h"
|
||||
|
||||
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 { \
|
||||
bool operator()(const T &x, const T &y) const { return x op y; } \
|
||||
struct type { \
|
||||
|
@ -22,24 +24,24 @@ namespace octa {
|
|||
}; \
|
||||
};
|
||||
|
||||
OCTA_DEFINE_BINARY_OP(Less, <, bool)
|
||||
OCTA_DEFINE_BINARY_OP(LessEqual, <=, bool)
|
||||
OCTA_DEFINE_BINARY_OP(Greater, >, bool)
|
||||
OCTA_DEFINE_BINARY_OP(GreaterEqual, >=, bool)
|
||||
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(Less, <, bool)
|
||||
__OCTA_DEFINE_BINARY_OP(LessEqual, <=, bool)
|
||||
__OCTA_DEFINE_BINARY_OP(Greater, >, bool)
|
||||
__OCTA_DEFINE_BINARY_OP(GreaterEqual, >=, bool)
|
||||
__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)
|
||||
|
||||
#undef OCTA_DEFINE_BINARY_OP
|
||||
#undef __OCTA_DEFINE_BINARY_OP
|
||||
|
||||
template<typename T> struct LogicalNot {
|
||||
bool operator()(const T &x) const { return !x; }
|
||||
|
@ -93,6 +95,8 @@ namespace octa {
|
|||
return BinaryNegate<T>(fn);
|
||||
}
|
||||
|
||||
/* reference wrapper */
|
||||
|
||||
template<typename T>
|
||||
struct ReferenceWrapper {
|
||||
typedef T type;
|
||||
|
@ -126,64 +130,64 @@ namespace octa {
|
|||
}
|
||||
template<typename T> void cref(const T &&) = delete;
|
||||
|
||||
namespace internal {
|
||||
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;
|
||||
};
|
||||
/* mem_fn */
|
||||
|
||||
template<typename R, typename T>
|
||||
class MemFn {
|
||||
R T::*p_ptr;
|
||||
public:
|
||||
struct type: MemTypes<T, R> {};
|
||||
|
||||
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()(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, typename> struct __OctaMemTypes;
|
||||
template<typename T, typename R, typename ...A>
|
||||
struct __OctaMemTypes<T, R(A...)> {
|
||||
typedef R result;
|
||||
typedef T argument;
|
||||
};
|
||||
template<typename T, typename R, typename A>
|
||||
struct __OctaMemTypes<T, R(A)> {
|
||||
typedef R result;
|
||||
typedef T first;
|
||||
typedef A second;
|
||||
};
|
||||
template<typename T, typename R, typename ...A>
|
||||
struct __OctaMemTypes<T, R(A...) const> {
|
||||
typedef R result;
|
||||
typedef const T argument;
|
||||
};
|
||||
template<typename T, typename R, typename A>
|
||||
struct __OctaMemTypes<T, R(A) const> {
|
||||
typedef R result;
|
||||
typedef const T first;
|
||||
typedef A second;
|
||||
};
|
||||
|
||||
template<typename R, typename T>
|
||||
internal::MemFn<R, T> mem_fn(R T:: *ptr) {
|
||||
return internal::MemFn<R, T>(ptr);
|
||||
class __OctaMemFn {
|
||||
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
|
||||
|
@ -192,158 +196,161 @@ namespace octa {
|
|||
|
||||
template<typename> struct Function;
|
||||
|
||||
namespace internal {
|
||||
struct FunctorData {
|
||||
void *p1, *p2;
|
||||
};
|
||||
struct __OctaFunctorData {
|
||||
void *p1, *p2;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct FunctorInPlace {
|
||||
static constexpr bool value = sizeof(T) <= sizeof(FunctorData)
|
||||
&& (alignof(FunctorData) % alignof(T)) == 0
|
||||
&& octa::IsNothrowMoveConstructible<T>::value;
|
||||
};
|
||||
template<typename T>
|
||||
struct __OctaFunctorInPlace {
|
||||
static constexpr bool value = sizeof(T) <= sizeof(__OctaFunctorData)
|
||||
&& (alignof(__OctaFunctorData) % alignof(T)) == 0
|
||||
&& octa::IsNothrowMoveConstructible<T>::value;
|
||||
};
|
||||
|
||||
template<typename T, typename E = void>
|
||||
struct FunctorDataManager {
|
||||
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_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 T, typename E = void>
|
||||
struct __OctaFunctorDataManager {
|
||||
template<typename R, typename ...A>
|
||||
static R call(const __OctaFunctorData &s, A ...args) {
|
||||
return ((T &)s)(forward<A>(args)...);
|
||||
}
|
||||
|
||||
template<typename R, typename...>
|
||||
struct FunctionBase {
|
||||
struct type {
|
||||
typedef R result;
|
||||
};
|
||||
};
|
||||
static void store_f(__OctaFunctorData &s, T v) {
|
||||
new (&get_ref(s)) T(forward<T>(v));
|
||||
}
|
||||
|
||||
template<typename R, typename T>
|
||||
struct FunctionBase<R, T> {
|
||||
struct type {
|
||||
typedef R result;
|
||||
typedef T argument;
|
||||
};
|
||||
};
|
||||
static void move_f(__OctaFunctorData &lhs, __OctaFunctorData &&rhs) {
|
||||
new (&get_ref(lhs)) T(move(get_ref(rhs)));
|
||||
}
|
||||
|
||||
template<typename R, typename T, typename U>
|
||||
struct FunctionBase<R, T, U> {
|
||||
struct type {
|
||||
typedef R result;
|
||||
typedef T first;
|
||||
typedef U second;
|
||||
static void destroy_f(__OctaFunctorData &s) {
|
||||
get_ref(s).~T();
|
||||
}
|
||||
|
||||
static T &get_ref(const __OctaFunctorData &s) {
|
||||
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>
|
||||
struct Function<R(A...)>: internal::FunctionBase<R, A...> {
|
||||
struct Function<R(A...)>: __OctaFunction<R, A...> {
|
||||
Function( ) { initialize_empty(); }
|
||||
Function(nullptr_t) { initialize_empty(); }
|
||||
|
||||
|
@ -391,7 +398,7 @@ namespace octa {
|
|||
}
|
||||
|
||||
void swap(Function &f) {
|
||||
internal::ManagerStorage tmp;
|
||||
__OctaFMStorage tmp;
|
||||
f.p_stor.manager->call_move_and_destroy(tmp, move(f.p_stor));
|
||||
p_stor.manager->call_move_and_destroy(f.p_stor, move(p_stor));
|
||||
tmp.manager->call_move_and_destroy(p_stor, move(tmp));
|
||||
|
@ -401,21 +408,21 @@ namespace octa {
|
|||
operator bool() const { return p_call != nullptr; }
|
||||
|
||||
private:
|
||||
internal::ManagerStorage p_stor;
|
||||
R (*p_call)(const internal::FunctorData &, A...);
|
||||
__OctaFMStorage p_stor;
|
||||
R (*p_call)(const __OctaFunctorData &, A...);
|
||||
|
||||
template<typename T>
|
||||
void initialize(T f) {
|
||||
p_call = &internal::FunctorDataManager<T>::template call<R, A...>;
|
||||
p_stor.manager = &internal::get_default_manager<T>();
|
||||
internal::FunctorDataManager<T>::store_f(p_stor.data, forward<T>(f));
|
||||
p_call = &__OctaFunctorDataManager<T>::template call<R, A...>;
|
||||
p_stor.manager = &__octa_get_default_fm<T>();
|
||||
__OctaFunctorDataManager<T>::store_f(p_stor.data, forward<T>(f));
|
||||
}
|
||||
|
||||
void initialize_empty() {
|
||||
typedef R(*emptyf)(A...);
|
||||
p_call = nullptr;
|
||||
p_stor.manager = &internal::get_default_manager<emptyf>();
|
||||
internal::FunctorDataManager<emptyf>::store_f(p_stor.data, nullptr);
|
||||
p_stor.manager = &__octa_get_default_fm<emptyf>();
|
||||
__OctaFunctorDataManager<emptyf>::store_f(p_stor.data, nullptr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
46
octa/range.h
46
octa/range.h
|
@ -25,26 +25,24 @@ namespace octa {
|
|||
typedef typename T::type::reference reference;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
template<typename T>
|
||||
struct RangeIterator {
|
||||
RangeIterator(): p_range() {}
|
||||
explicit RangeIterator(const T &range): p_range(range) {}
|
||||
RangeIterator &operator++() {
|
||||
p_range.pop_first();
|
||||
return *this;
|
||||
}
|
||||
typename RangeTraits<T>::reference operator*() {
|
||||
return p_range.first();
|
||||
}
|
||||
typename RangeTraits<T>::reference operator*() const {
|
||||
return p_range.first();
|
||||
}
|
||||
bool operator!=(RangeIterator) const { return !p_range.empty(); }
|
||||
private:
|
||||
T p_range;
|
||||
};
|
||||
}
|
||||
template<typename T>
|
||||
struct __OctaRangeIterator {
|
||||
__OctaRangeIterator(): p_range() {}
|
||||
explicit __OctaRangeIterator(const T &range): p_range(range) {}
|
||||
__OctaRangeIterator &operator++() {
|
||||
p_range.pop_first();
|
||||
return *this;
|
||||
}
|
||||
typename RangeTraits<T>::reference operator*() {
|
||||
return p_range.first();
|
||||
}
|
||||
typename RangeTraits<T>::reference operator*() const {
|
||||
return p_range.first();
|
||||
}
|
||||
bool operator!=(__OctaRangeIterator) const { return !p_range.empty(); }
|
||||
private:
|
||||
T p_range;
|
||||
};
|
||||
|
||||
template<typename B, typename C, typename V, typename R = V &>
|
||||
struct InputRangeBase {
|
||||
|
@ -54,11 +52,11 @@ namespace octa {
|
|||
typedef R reference;
|
||||
};
|
||||
|
||||
internal::RangeIterator<B> begin() {
|
||||
return internal::RangeIterator<B>((const B &)*this);
|
||||
__OctaRangeIterator<B> begin() {
|
||||
return __OctaRangeIterator<B>((const B &)*this);
|
||||
}
|
||||
internal::RangeIterator<B> end() {
|
||||
return internal::RangeIterator<B>();
|
||||
__OctaRangeIterator<B> end() {
|
||||
return __OctaRangeIterator<B>();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue