deuglify functional.h

This commit is contained in:
q66 2015-06-03 23:27:09 +01:00
parent e130eb6cf0
commit 153812e91e

View file

@ -12,45 +12,46 @@
#include "octa/type_traits.h" #include "octa/type_traits.h"
namespace octa { namespace octa {
/* basic function objects */ /* basic function objects */
#define __OCTA_DEFINE_BINARY_OP(_name, _op, _rettype) \ #define OCTA_DEFINE_BINARY_OP(_name, _op, _rettype) \
template<typename _T> struct _name { \ template<typename _T> struct _name { \
_rettype operator()(const _T &__x, const _T &__y) const { \ _rettype operator()(const _T &x, const _T &y) const { \
return __x _op __y; \ return x _op y; \
} \ } \
typedef _T FirstArgument; \ typedef _T FirstArgument; \
typedef _T SecondArgument; \ typedef _T SecondArgument; \
typedef _rettype Result; \ typedef _rettype Result; \
}; };
__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; }
typedef _T Argument; typedef _T Argument;
typedef bool Result; typedef bool Result;
}; };
template<typename _T> struct Negate { template<typename _T> struct Negate {
bool operator()(const _T &__x) const { return -__x; } bool operator()(const _T &x) const { return -x; }
typedef _T Argument; typedef _T Argument;
typedef _T Result; typedef _T Result;
}; };
@ -60,166 +61,170 @@ namespace octa {
typedef typename _T::SecondArgument SecondArgument; typedef typename _T::SecondArgument SecondArgument;
typedef bool Result; typedef bool Result;
explicit BinaryNegate(const _T &__f): __fn(__f) {} explicit BinaryNegate(const _T &f): p_fn(f) {}
bool operator()(const FirstArgument &__x, bool operator()(const FirstArgument &x,
const SecondArgument &__y) { const SecondArgument &y) {
return !__fn(__x, __y); return !p_fn(x, y);
} }
private: private:
_T __fn; _T p_fn;
}; };
template<typename _T> struct UnaryNegate { template<typename _T> struct UnaryNegate {
typedef typename _T::Argument Argument; typedef typename _T::Argument Argument;
typedef bool Result; typedef bool Result;
explicit UnaryNegate(const _T &__f): __fn(__f) {} explicit UnaryNegate(const _T &f): p_fn(f) {}
bool operator()(const Argument &__x) { bool operator()(const Argument &x) {
return !__fn(__x); return !p_fn(x);
} }
private: private:
_T __fn; _T p_fn;
}; };
template<typename _T> UnaryNegate<_T> not1(const _T &__fn) { template<typename _T> UnaryNegate<_T> not1(const _T &fn) {
return UnaryNegate<_T>(__fn); return UnaryNegate<_T>(fn);
} }
template<typename _T> BinaryNegate<_T> not2(const _T &__fn) { template<typename _T> BinaryNegate<_T> not2(const _T &fn) {
return BinaryNegate<_T>(__fn); return BinaryNegate<_T>(fn);
} }
/* hash */ /* hash */
template<typename _T> struct Hash; template<typename _T> struct Hash;
template<typename _T> struct __OctaHashBase { namespace detail {
template<typename _T> struct HashBase {
typedef _T Argument; typedef _T Argument;
typedef size_t Result; typedef size_t Result;
size_t operator()(_T __v) const { size_t operator()(_T v) const {
return size_t(__v); return size_t(v);
} }
}; };
}
#define __OCTA_HASH_BASIC(_T) template<> struct Hash<_T>: __OctaHashBase<_T> {}; #define OCTA_HASH_BASIC(_T) template<> struct Hash<_T>: octa::detail::HashBase<_T> {};
__OCTA_HASH_BASIC(bool) OCTA_HASH_BASIC(bool)
__OCTA_HASH_BASIC(char) OCTA_HASH_BASIC(char)
__OCTA_HASH_BASIC(schar) OCTA_HASH_BASIC(schar)
__OCTA_HASH_BASIC(uchar) OCTA_HASH_BASIC(uchar)
__OCTA_HASH_BASIC(char16_t) OCTA_HASH_BASIC(char16_t)
__OCTA_HASH_BASIC(char32_t) OCTA_HASH_BASIC(char32_t)
__OCTA_HASH_BASIC(wchar_t) OCTA_HASH_BASIC(wchar_t)
__OCTA_HASH_BASIC(short) OCTA_HASH_BASIC(short)
__OCTA_HASH_BASIC(ushort) OCTA_HASH_BASIC(ushort)
__OCTA_HASH_BASIC(int) OCTA_HASH_BASIC(int)
__OCTA_HASH_BASIC(uint) OCTA_HASH_BASIC(uint)
__OCTA_HASH_BASIC(long) OCTA_HASH_BASIC(long)
__OCTA_HASH_BASIC(ulong) OCTA_HASH_BASIC(ulong)
#undef __OCTA_HASH_BASIC #undef OCTA_HASH_BASIC
static inline size_t __octa_mem_hash(const void *__p, size_t __l) { namespace detail {
const uchar *__d = (const uchar *)__p; static inline size_t mem_hash(const void *p, size_t l) {
size_t __h = 5381; const uchar *d = (const uchar *)p;
for (size_t __i = 0; __i < __l; ++__i) __h = ((__h << 5) + __h) ^ __d[__i]; size_t h = 5381;
return __h; for (size_t i = 0; i < l; ++i) h = ((h << 5) + h) ^ d[i];
return h;
} }
template<typename _T, size_t = sizeof(_T) / sizeof(size_t)> template<typename _T, size_t = sizeof(_T) / sizeof(size_t)>
struct __OctaScalarHash; struct ScalarHash;
template<typename _T> struct __OctaScalarHash<_T, 0> { template<typename _T> struct ScalarHash<_T, 0> {
typedef _T Argument; typedef _T Argument;
typedef size_t Result; typedef size_t Result;
size_t operator()(_T __v) const { size_t operator()(_T v) const {
union { _T __v; size_t __h; } __u; union { _T v; size_t h; } u;
__u.__h = 0; u.h = 0;
__u.__v = __v; u.v = v;
return __u.__h; return u.h;
} }
}; };
template<typename _T> struct __OctaScalarHash<_T, 1> { template<typename _T> struct ScalarHash<_T, 1> {
typedef _T Argument; typedef _T Argument;
typedef size_t Result; typedef size_t Result;
size_t operator()(_T __v) const { size_t operator()(_T v) const {
union { _T __v; size_t __h; } __u; union { _T v; size_t h; } u;
__u.__v = __v; u.v = v;
return __u.__h; return u.h;
} }
}; };
template<typename _T> struct __OctaScalarHash<_T, 2> { template<typename _T> struct ScalarHash<_T, 2> {
typedef _T Argument; typedef _T Argument;
typedef size_t Result; typedef size_t Result;
size_t operator()(_T __v) const { size_t operator()(_T v) const {
union { _T __v; struct { size_t __h1, __h2; }; } __u; union { _T v; struct { size_t h1, h2; }; } u;
__u.__v = __v; u.v = v;
return __octa_mem_hash((const void *)&__u, sizeof(__u)); return mem_hash((const void *)&u, sizeof(u));
} }
}; };
template<typename _T> struct __OctaScalarHash<_T, 3> { template<typename _T> struct ScalarHash<_T, 3> {
typedef _T Argument; typedef _T Argument;
typedef size_t Result; typedef size_t Result;
size_t operator()(_T __v) const { size_t operator()(_T v) const {
union { _T __v; struct { size_t __h1, __h2, __h3; }; } __u; union { _T v; struct { size_t h1, h2, h3; }; } u;
__u.__v = __v; u.v = v;
return __octa_mem_hash((const void *)&__u, sizeof(__u)); return mem_hash((const void *)&u, sizeof(u));
} }
}; };
template<typename _T> struct __OctaScalarHash<_T, 4> { template<typename _T> struct ScalarHash<_T, 4> {
typedef _T Argument; typedef _T Argument;
typedef size_t Result; typedef size_t Result;
size_t operator()(_T __v) const { size_t operator()(_T v) const {
union { _T __v; struct { size_t __h1, __h2, __h3, __h4; }; } __u; union { _T v; struct { size_t h1, h2, h3, h4; }; } u;
__u.__v = __v; u.v = v;
return __octa_mem_hash((const void *)&__u, sizeof(__u)); return mem_hash((const void *)&u, sizeof(u));
}
};
} /* namespace detail */
template<> struct Hash<llong>: octa::detail::ScalarHash<llong> {};
template<> struct Hash<ullong>: octa::detail::ScalarHash<ullong> {};
template<> struct Hash<float>: octa::detail::ScalarHash<float> {
size_t operator()(float v) const {
if (v == 0) return 0;
return octa::detail::ScalarHash<float>::operator()(v);
} }
}; };
template<> struct Hash<llong>: __OctaScalarHash<llong> {}; template<> struct Hash<double>: octa::detail::ScalarHash<double> {
template<> struct Hash<ullong>: __OctaScalarHash<ullong> {}; size_t operator()(double v) const {
if (v == 0) return 0;
template<> struct Hash<float>: __OctaScalarHash<float> { return octa::detail::ScalarHash<double>::operator()(v);
size_t operator()(float __v) const {
if (__v == 0) return 0;
return __OctaScalarHash<float>::operator()(__v);
} }
}; };
template<> struct Hash<double>: __OctaScalarHash<double> { template<> struct Hash<ldouble>: octa::detail::ScalarHash<ldouble> {
size_t operator()(double __v) const { size_t operator()(ldouble v) const {
if (__v == 0) return 0; if (v == 0) return 0;
return __OctaScalarHash<double>::operator()(__v);
}
};
template<> struct Hash<ldouble>: __OctaScalarHash<ldouble> {
size_t operator()(ldouble __v) const {
if (__v == 0) return 0;
#ifdef __i386__ #ifdef __i386__
union { ldouble __v; struct { size_t __h1, __h2, __h3, __h4; }; } __u; union { ldouble v; struct { size_t h1, h2, h3, h4; }; } u;
__u.__h1 = __u.__h2 = __u.__h3 = __u.__h4 = 0; u.h1 = u.h2 = u.h3 = u.h4 = 0;
__u.__v = __v; u.v = v;
return (__u.__h1 ^ __u.__h2 ^ __u.__h3 ^ __u.__h4); return (u.h1 ^ u.h2 ^ u.h3 ^ u.h4);
#else #else
#ifdef __x86_64__ #ifdef __x86_64__
union { ldouble __v; struct { size_t __h1, __h2; }; } __u; union { ldouble v; struct { size_t h1, h2; }; } u;
__u.__h1 = __u.__h2 = 0; u.h1 = u.h2 = 0;
__u.__v = __v; u.v = v;
return (__u.__h1 ^ __u.__h2); return (u.h1 ^ u.h2);
#else #else
return __OctaScalarHash<ldouble>::operator()(__v); return octa::detail::ScalarHash<ldouble>::operator()(v);
#endif #endif
#endif #endif
} }
@ -229,10 +234,10 @@ namespace octa {
typedef _T *Argument; typedef _T *Argument;
typedef size_t Result; typedef size_t Result;
size_t operator()(_T *__v) const { size_t operator()(_T *v) const {
union { _T *__v; size_t __h; } __u; union { _T *v; size_t h; } u;
__u.__v = __v; u.v = v;
return __octa_mem_hash((const void *)&__u, sizeof(__u)); return octa::detail::mem_hash((const void *)&u, sizeof(u));
} }
}; };
@ -242,95 +247,97 @@ namespace octa {
struct ReferenceWrapper { struct ReferenceWrapper {
typedef _T type; typedef _T type;
ReferenceWrapper(_T &__v): __ptr(address_of(__v)) {} ReferenceWrapper(_T &v): p_ptr(address_of(v)) {}
ReferenceWrapper(const ReferenceWrapper &) = default; ReferenceWrapper(const ReferenceWrapper &) = default;
ReferenceWrapper(_T &&) = delete; ReferenceWrapper(_T &&) = delete;
ReferenceWrapper &operator=(const ReferenceWrapper &) = default; ReferenceWrapper &operator=(const ReferenceWrapper &) = default;
operator _T &() const { return *__ptr; } operator _T &() const { return *p_ptr; }
_T &get() const { return *__ptr; } _T &get() const { return *p_ptr; }
private: private:
_T *__ptr; _T *p_ptr;
}; };
template<typename _T> template<typename _T>
ReferenceWrapper<_T> ref(_T &__v) { ReferenceWrapper<_T> ref(_T &v) {
return ReferenceWrapper<_T>(__v); return ReferenceWrapper<_T>(v);
} }
template<typename _T> template<typename _T>
ReferenceWrapper<_T> ref(ReferenceWrapper<_T> __v) { ReferenceWrapper<_T> ref(ReferenceWrapper<_T> v) {
return 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> template<typename _T>
ReferenceWrapper<const _T> cref(const _T &__v) { ReferenceWrapper<const _T> cref(const _T &v) {
return ReferenceWrapper<_T>(__v); return ReferenceWrapper<_T>(v);
} }
template<typename _T> template<typename _T>
ReferenceWrapper<const _T> cref(ReferenceWrapper<_T> __v) { ReferenceWrapper<const _T> cref(ReferenceWrapper<_T> v) {
return 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 */ /* mem_fn */
template<typename, typename> struct __OctaMemTypes; namespace detail {
template<typename, typename> struct MemTypes;
template<typename _T, typename _R, typename ..._A> template<typename _T, typename _R, typename ..._A>
struct __OctaMemTypes<_T, _R(_A...)> { struct MemTypes<_T, _R(_A...)> {
typedef _R Result; typedef _R Result;
typedef _T Argument; typedef _T Argument;
}; };
template<typename _T, typename _R, typename _A> template<typename _T, typename _R, typename _A>
struct __OctaMemTypes<_T, _R(_A)> { struct MemTypes<_T, _R(_A)> {
typedef _R Result; typedef _R Result;
typedef _T FirstArgument; typedef _T FirstArgument;
typedef _A SecondArgument; typedef _A SecondArgument;
}; };
template<typename _T, typename _R, typename ..._A> template<typename _T, typename _R, typename ..._A>
struct __OctaMemTypes<_T, _R(_A...) const> { struct MemTypes<_T, _R(_A...) const> {
typedef _R Result; typedef _R Result;
typedef const _T Argument; typedef const _T Argument;
}; };
template<typename _T, typename _R, typename _A> template<typename _T, typename _R, typename _A>
struct __OctaMemTypes<_T, _R(_A) const> { struct MemTypes<_T, _R(_A) const> {
typedef _R Result; typedef _R Result;
typedef const _T FirstArgument; typedef const _T FirstArgument;
typedef _A SecondArgument; typedef _A SecondArgument;
}; };
template<typename _R, typename _T> template<typename _R, typename _T>
class __OctaMemFn: __OctaMemTypes<_T, _R> { class MemFn: MemTypes<_T, _R> {
_R _T::*__ptr; _R _T::*p_ptr;
public: public:
__OctaMemFn(_R _T::*__ptr): __ptr(__ptr) {} MemFn(_R _T::*ptr): p_ptr(ptr) {}
template<typename... _A> template<typename... _A>
auto operator()(_T &__obj, _A &&...__args) -> auto operator()(_T &obj, _A &&...args) ->
decltype(((__obj).*(__ptr))(forward<_A>(__args)...)) { decltype(((obj).*(p_ptr))(forward<_A>(args)...)) {
return ((__obj).*(__ptr))(forward<_A>(__args)...); return ((obj).*(p_ptr))(forward<_A>(args)...);
} }
template<typename... _A> template<typename... _A>
auto operator()(const _T &__obj, _A &&...__args) -> auto operator()(const _T &obj, _A &&...args) ->
decltype(((__obj).*(__ptr))(forward<_A>(__args)...)) const { decltype(((obj).*(p_ptr))(forward<_A>(args)...)) const {
return ((__obj).*(__ptr))(forward<_A>(__args)...); return ((obj).*(p_ptr))(forward<_A>(args)...);
} }
template<typename... _A> template<typename... _A>
auto operator()(_T *__obj, _A &&...__args) -> auto operator()(_T *obj, _A &&...args) ->
decltype(((__obj)->*(__ptr))(forward<_A>(__args)...)) { decltype(((obj)->*(p_ptr))(forward<_A>(args)...)) {
return ((__obj)->*(__ptr))(forward<_A>(__args)...); return ((obj)->*(p_ptr))(forward<_A>(args)...);
} }
template<typename... _A> template<typename... _A>
auto operator()(const _T *__obj, _A &&...__args) -> auto operator()(const _T *obj, _A &&...args) ->
decltype(((__obj)->*(__ptr))(forward<_A>(__args)...)) const { decltype(((obj)->*(p_ptr))(forward<_A>(args)...)) const {
return ((__obj)->*(__ptr))(forward<_A>(__args)...); return ((obj)->*(p_ptr))(forward<_A>(args)...);
} }
}; };
} /* namespace detail */
template<typename _R, typename _T> template<typename _R, typename _T>
__OctaMemFn<_R, _T> mem_fn(_R _T:: *__ptr) { octa::detail::MemFn<_R, _T> mem_fn(_R _T:: *ptr) {
return __OctaMemFn<_R, _T>(__ptr); return octa::detail::MemFn<_R, _T>(ptr);
} }
/* function impl /* function impl
@ -339,304 +346,311 @@ namespace octa {
template<typename> struct Function; template<typename> struct Function;
struct __OctaFunctorData { namespace detail {
void *__p1, *__p2; struct FunctorData {
void *p1, *p2;
}; };
template<typename _T> template<typename _T>
struct __OctaFunctorInPlace { struct FunctorInPlace {
static constexpr bool value = sizeof(_T) <= sizeof(__OctaFunctorData) static constexpr bool value = sizeof(_T) <= sizeof(FunctorData)
&& (alignof(__OctaFunctorData) % alignof(_T)) == 0 && (alignof(FunctorData) % alignof(_T)) == 0
&& octa::IsMoveConstructible<_T>::value; && octa::IsMoveConstructible<_T>::value;
}; };
template<typename _T, typename _E = void> template<typename _T, typename _E = void>
struct __OctaFunctorDataManager { struct FunctorDataManager {
template<typename _R, typename ..._A> template<typename _R, typename ..._A>
static _R __call(const __OctaFunctorData &__s, _A ...__args) { static _R call(const FunctorData &s, _A ...args) {
return ((_T &)__s)(octa::forward<_A>(__args)...); return ((_T &)s)(octa::forward<_A>(args)...);
} }
static void __store_f(__OctaFunctorData &__s, _T __v) { static void store_f(FunctorData &s, _T v) {
new (&__get_ref(__s)) _T(octa::forward<_T>(__v)); new (&get_ref(s)) _T(octa::forward<_T>(v));
} }
static void __move_f(__OctaFunctorData &__lhs, __OctaFunctorData &&__rhs) { 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(__OctaFunctorData &__s) { static void destroy_f(FunctorData &s) {
__get_ref(__s).~_T(); get_ref(s).~_T();
} }
static _T &__get_ref(const __OctaFunctorData &__s) { static _T &get_ref(const FunctorData &s) {
return (_T &)__s; return (_T &)s;
} }
}; };
template<typename _T> template<typename _T>
struct __OctaFunctorDataManager<_T, EnableIf<!__OctaFunctorInPlace<_T>::value>> { struct FunctorDataManager<_T,
EnableIf<!FunctorInPlace<_T>::value>
> {
template<typename _R, typename ..._A> template<typename _R, typename ..._A>
static _R __call(const __OctaFunctorData &__s, _A ...__args) { static _R call(const FunctorData &s, _A ...args) {
return (*(_T *&)__s)(octa::forward<_A>(__args)...); return (*(_T *&)s)(octa::forward<_A>(args)...);
} }
static void __store_f(__OctaFunctorData &__s, _T __v) { static void store_f(FunctorData &s, _T v) {
new (&__get_ptr_ref(__s)) _T *(new _T(octa::forward<_T>(__v))); new (&get_ptr_ref(s)) _T *(new _T(octa::forward<_T>(v)));
} }
static void __move_f(__OctaFunctorData &__lhs, __OctaFunctorData &&__rhs) { 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; get_ptr_ref(rhs) = nullptr;
} }
static void __destroy_f(__OctaFunctorData &__s) { static void destroy_f(FunctorData &s) {
_T *&__ptr = __get_ptr_ref(__s); _T *&ptr = get_ptr_ref(s);
if (!__ptr) return; if (!ptr) return;
delete __ptr; delete ptr;
__ptr = nullptr; ptr = nullptr;
} }
static _T &__get_ref(const __OctaFunctorData &__s) { static _T &get_ref(const FunctorData &s) {
return *__get_ptr_ref(__s); return *get_ptr_ref(s);
} }
static _T *&__get_ptr_ref(__OctaFunctorData &__s) { static _T *&get_ptr_ref(FunctorData &s) {
return (_T *&)__s; return (_T *&)s;
} }
static _T *&__get_ptr_ref(const __OctaFunctorData &__s) { static _T *&get_ptr_ref(const FunctorData &s) {
return (_T *&)__s; return (_T *&)s;
} }
}; };
struct __OctaFunctionManager; struct FunctionManager;
struct __OctaFmStorage { struct FmStorage {
__OctaFunctorData __data; FunctorData data;
const __OctaFunctionManager *__manager; const FunctionManager *manager;
}; };
template<typename _T> template<typename _T>
static const __OctaFunctionManager &__octa_get_default_fm(); static const FunctionManager &get_default_fm();
struct __OctaFunctionManager { struct FunctionManager {
template<typename _T> template<typename _T>
inline static const __OctaFunctionManager __create_default_manager() { inline static const FunctionManager create_default_manager() {
return __OctaFunctionManager { return FunctionManager {
&__call_move_and_destroy<_T>, &call_move_and_destroy<_T>,
&__call_copy<_T>, &call_copy<_T>,
&__call_destroy<_T> &call_destroy<_T>
}; };
} }
void (* const __call_move_and_destroyf)(__OctaFmStorage &__lhs, void (* const call_move_and_destroyf)(FmStorage &lhs,
__OctaFmStorage &&__rhs); FmStorage &&rhs);
void (* const __call_copyf)(__OctaFmStorage &__lhs, void (* const call_copyf)(FmStorage &lhs,
const __OctaFmStorage &__rhs); const FmStorage &rhs);
void (* const __call_destroyf)(__OctaFmStorage &__s); void (* const call_destroyf)(FmStorage &s);
template<typename _T> template<typename _T>
static void __call_move_and_destroy(__OctaFmStorage &__lhs, static void call_move_and_destroy(FmStorage &lhs,
__OctaFmStorage &&__rhs) { FmStorage &&rhs) {
typedef __OctaFunctorDataManager<_T> _spec; typedef FunctorDataManager<_T> _spec;
_spec::__move_f(__lhs.__data, octa::move(__rhs.__data)); _spec::move_f(lhs.data, octa::move(rhs.data));
_spec::__destroy_f(__rhs.__data); _spec::destroy_f(rhs.data);
__lhs.__manager = &__octa_get_default_fm<_T>(); lhs.manager = &get_default_fm<_T>();
} }
template<typename _T> template<typename _T>
static void __call_copy(__OctaFmStorage &__lhs, static void call_copy(FmStorage &lhs,
const __OctaFmStorage &__rhs) { const FmStorage &rhs) {
typedef __OctaFunctorDataManager<_T> _spec; typedef FunctorDataManager<_T> _spec;
__lhs.__manager = &__octa_get_default_fm<_T>(); lhs.manager = &get_default_fm<_T>();
_spec::__store_f(__lhs.__data, _spec::__get_ref(__rhs.__data)); _spec::store_f(lhs.data, _spec::get_ref(rhs.data));
} }
template<typename _T> template<typename _T>
static void __call_destroy(__OctaFmStorage &__s) { static void call_destroy(FmStorage &s) {
typedef __OctaFunctorDataManager<_T> _spec; typedef FunctorDataManager<_T> _spec;
_spec::__destroy_f(__s.__data); _spec::destroy_f(s.data);
} }
}; };
template<typename _T> template<typename _T>
inline static const __OctaFunctionManager &__octa_get_default_fm() { inline static const FunctionManager &get_default_fm() {
static const __OctaFunctionManager __def_manager static const FunctionManager def_manager
= __OctaFunctionManager::__create_default_manager<_T>(); = FunctionManager::create_default_manager<_T>();
return __def_manager; return def_manager;
} }
template<typename _R, typename...> template<typename _R, typename...>
struct __OctaFunction { struct FunctionBase {
typedef _R Result; typedef _R Result;
}; };
template<typename _R, typename _T> template<typename _R, typename _T>
struct __OctaFunction<_R, _T> { struct FunctionBase<_R, _T> {
typedef _R Result; typedef _R Result;
typedef _T Argument; typedef _T Argument;
}; };
template<typename _R, typename _T, typename _U> template<typename _R, typename _T, typename _U>
struct __OctaFunction<_R, _T, _U> { struct FunctionBase<_R, _T, _U> {
typedef _R Result; typedef _R Result;
typedef _T FirstArgument; typedef _T FirstArgument;
typedef _U SecondArgument; typedef _U SecondArgument;
}; };
template<typename, typename> template<typename, typename>
struct __OctaIsValidFunctor { struct IsValidFunctor {
static constexpr bool value = false; static constexpr bool value = false;
}; };
template<typename _R, typename ..._A> template<typename _R, typename ..._A>
struct __OctaIsValidFunctor<Function<_R(_A...)>, _R(_A...)> { struct IsValidFunctor<Function<_R(_A...)>, _R(_A...)> {
static constexpr bool value = false; static constexpr bool value = false;
}; };
struct __OctaEmpty { struct Empty {
}; };
template<typename _T> template<typename _T>
_T __octa_func_to_functor(_T &&__f) { _T func_to_functor(_T &&f) {
return octa::forward<_T>(__f); return octa::forward<_T>(f);
} }
template<typename _RR, typename _T, typename ..._AA> template<typename _RR, typename _T, typename ..._AA>
auto __octa_func_to_functor(_RR (_T::*__f)(_AA...)) auto func_to_functor(_RR (_T::*f)(_AA...))
-> decltype(mem_fn(__f)) { -> decltype(mem_fn(f)) {
return mem_fn(__f); return mem_fn(f);
} }
template<typename _RR, typename _T, typename ..._AA> template<typename _RR, typename _T, typename ..._AA>
auto __octa_func_to_functor(_RR (_T::*__f)(_AA...) const) auto func_to_functor(_RR (_T::*f)(_AA...) const)
-> decltype(mem_fn(__f)) { -> decltype(mem_fn(f)) {
return mem_fn(__f); return mem_fn(f);
} }
template<typename _T, typename _R, typename ..._A> template<typename _T, typename _R, typename ..._A>
struct __OctaIsValidFunctor<_T, _R(_A...)> { struct IsValidFunctor<_T, _R(_A...)> {
template<typename _U> template<typename _U>
static decltype(__octa_func_to_functor(octa::declval<_U>()) static decltype(func_to_functor(octa::declval<_U>())
(octa::declval<_A>()...)) __test(_U *); (octa::declval<_A>()...)) test(_U *);
template<typename> template<typename>
static __OctaEmpty __test(...); static Empty test(...);
static constexpr bool value = octa::IsConvertible< static constexpr bool value = octa::IsConvertible<
decltype(__test<_T>(nullptr)), _R decltype(test<_T>(nullptr)), _R
>::value; >::value;
}; };
} /* namespace detail */
template<typename _R, typename ..._A> template<typename _R, typename ..._A>
struct Function<_R(_A...)>: __OctaFunction<_R, _A...> { struct Function<_R(_A...)>: octa::detail::FunctionBase<_R, _A...> {
Function( ) { __init_empty(); } Function( ) { init_empty(); }
Function(nullptr_t) { __init_empty(); } Function(nullptr_t) { init_empty(); }
Function(Function &&__f) { Function(Function &&f) {
__init_empty(); init_empty();
swap(__f); swap(f);
} }
Function(const Function &__f): __call(__f.__call) { Function(const Function &f): p_call(f.p_call) {
__f.__stor.__manager->__call_copyf(__stor, __f.__stor); f.p_stor.manager->call_copyf(p_stor, f.p_stor);
} }
template<typename _T> template<typename _T>
Function(_T __f, EnableIf<__OctaIsValidFunctor<_T, _R(_A...)>::value, __OctaEmpty> Function(_T f, EnableIf<
= __OctaEmpty()) { octa::detail::IsValidFunctor<_T, _R(_A...)>::value,
if (__func_is_null(__f)) { octa::detail::Empty
__init_empty(); > = octa::detail::Empty()) {
if (func_is_null(f)) {
init_empty();
return; return;
} }
__initialize(__octa_func_to_functor(octa::forward<_T>(__f))); initialize(octa::detail::func_to_functor(octa::forward<_T>(f)));
} }
~Function() { ~Function() {
__stor.__manager->__call_destroyf(__stor); p_stor.manager->call_destroyf(p_stor);
} }
Function &operator=(Function &&__f) { Function &operator=(Function &&f) {
__stor.__manager->__call_destroyf(__stor); p_stor.manager->call_destroyf(p_stor);
swap(__f); swap(f);
return *this; return *this;
} }
Function &operator=(const Function &__f) { Function &operator=(const Function &f) {
__stor.__manager->__call_destroyf(__stor); p_stor.manager->call_destroyf(p_stor);
__f.__stor.__manager->__call_copyf(__stor, __f.__stor); f.p_stor.manager->call_copyf(p_stor, f.p_stor);
return *this; return *this;
}; };
_R operator()(_A ...__args) const { _R operator()(_A ...args) const {
return __call(__stor.__data, octa::forward<_A>(__args)...); return p_call(p_stor.data, octa::forward<_A>(args)...);
} }
template<typename _F> void assign(_F &&__f) { template<typename _F> void assign(_F &&f) {
Function(octa::forward<_F>(__f)).swap(*this); Function(octa::forward<_F>(f)).swap(*this);
} }
void swap(Function &__f) { void swap(Function &f) {
__OctaFmStorage __tmp; octa::detail::FmStorage tmp;
__f.__stor.__manager->__call_move_and_destroyf(__tmp, f.p_stor.manager->call_move_and_destroyf(tmp,
octa::move(__f.__stor)); octa::move(f.p_stor));
__stor.__manager->__call_move_and_destroyf(__f.__stor, p_stor.manager->call_move_and_destroyf(f.p_stor,
octa::move(__stor)); octa::move(p_stor));
__tmp.__manager->__call_move_and_destroyf(__stor, tmp.manager->call_move_and_destroyf(p_stor,
octa::move(__tmp)); octa::move(tmp));
octa::swap(__call, __f.__call); octa::swap(p_call, f.p_call);
} }
operator bool() const { return __call != nullptr; } operator bool() const { return p_call != nullptr; }
private: private:
__OctaFmStorage __stor; octa::detail::FmStorage p_stor;
_R (*__call)(const __OctaFunctorData &, _A...); _R (*p_call)(const octa::detail::FunctorData &, _A...);
template<typename _T> template<typename _T>
void __initialize(_T __f) { void initialize(_T f) {
__call = &__OctaFunctorDataManager<_T>::template __call<_R, _A...>; p_call = &octa::detail::FunctorDataManager<_T>::template call<_R, _A...>;
__stor.__manager = &__octa_get_default_fm<_T>(); p_stor.manager = &octa::detail::get_default_fm<_T>();
__OctaFunctorDataManager<_T>::__store_f(__stor.__data, octa::detail::FunctorDataManager<_T>::store_f(p_stor.data,
octa::forward<_T>(__f)); octa::forward<_T>(f));
} }
void __init_empty() { void init_empty() {
typedef _R(*__emptyf)(_A...); typedef _R(*emptyf)(_A...);
__call = nullptr; p_call = nullptr;
__stor.__manager = &__octa_get_default_fm<__emptyf>(); p_stor.manager = &octa::detail::get_default_fm<emptyf>();
__OctaFunctorDataManager<__emptyf>::__store_f(__stor.__data, nullptr); octa::detail::FunctorDataManager<emptyf>::store_f(p_stor.data, nullptr);
} }
template<typename _T> template<typename _T>
static bool __func_is_null(const _T &) { return false; } 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; return fptr == nullptr;
} }
template<typename _RR, typename _T, typename ..._AA> template<typename _RR, typename _T, typename ..._AA>
static bool __func_is_null(_RR (_T::* const &__fptr)(_AA...)) { static bool func_is_null(_RR (_T::* const &fptr)(_AA...)) {
return __fptr == nullptr; return fptr == nullptr;
} }
template<typename _RR, typename _T, typename ..._AA> template<typename _RR, typename _T, typename ..._AA>
static bool __func_is_null(_RR (_T::* const &__fptr)(_AA...) const) { static bool func_is_null(_RR (_T::* const &fptr)(_AA...) const) {
return __fptr == nullptr; return fptr == nullptr;
} }
}; };
template<typename _T> template<typename _T>
bool operator==(nullptr_t, const Function<_T> &__rhs) { return !__rhs; } bool operator==(nullptr_t, const Function<_T> &rhs) { return !rhs; }
template<typename _T> template<typename _T>
bool operator==(const Function<_T> &__lhs, nullptr_t) { return !__lhs; } bool operator==(const Function<_T> &lhs, nullptr_t) { return !lhs; }
template<typename _T> template<typename _T>
bool operator!=(nullptr_t, const Function<_T> &__rhs) { return __rhs; } bool operator!=(nullptr_t, const Function<_T> &rhs) { return rhs; }
template<typename _T> template<typename _T>
bool operator!=(const Function<_T> &__lhs, nullptr_t) { return __lhs; } bool operator!=(const Function<_T> &lhs, nullptr_t) { return lhs; }
}
} /* namespace octa */
#endif #endif