2015-04-18 01:35:36 +00:00
|
|
|
/* Function objects for OctaSTD.
|
|
|
|
*
|
|
|
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef OCTA_FUNCTIONAL_H
|
|
|
|
#define OCTA_FUNCTIONAL_H
|
|
|
|
|
2015-04-22 17:42:58 +00:00
|
|
|
#include "octa/new.h"
|
2015-04-18 18:02:44 +00:00
|
|
|
#include "octa/memory.h"
|
2015-04-22 17:42:58 +00:00
|
|
|
#include "octa/utility.h"
|
2015-04-25 15:13:21 +00:00
|
|
|
#include "octa/type_traits.h"
|
2015-04-18 18:02:44 +00:00
|
|
|
|
2015-04-18 01:35:36 +00:00
|
|
|
namespace octa {
|
2015-04-24 17:16:35 +00:00
|
|
|
/* basic function objects */
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
#define __OCTA_DEFINE_BINARY_OP(_name, _op, _rettype) \
|
|
|
|
template<typename _T> struct _name { \
|
|
|
|
_rettype operator()(const _T &__x, const _T &__y) const { \
|
|
|
|
return __x _op __y; \
|
|
|
|
} \
|
|
|
|
typedef _T FirstArgType; \
|
|
|
|
typedef _T SecondArgType; \
|
|
|
|
typedef _rettype ResultType; \
|
2015-04-18 01:35:36 +00:00
|
|
|
};
|
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
__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)
|
2015-06-01 23:57:34 +00:00
|
|
|
__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)
|
2015-04-24 17:16:35 +00:00
|
|
|
|
|
|
|
#undef __OCTA_DEFINE_BINARY_OP
|
2015-04-18 01:35:36 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> struct LogicalNot {
|
|
|
|
bool operator()(const _T &__x) const { return !__x; }
|
|
|
|
typedef _T ArgType;
|
2015-05-03 22:44:48 +00:00
|
|
|
typedef bool ResultType;
|
2015-04-18 01:35:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> struct Negate {
|
|
|
|
bool operator()(const _T &__x) const { return -__x; }
|
|
|
|
typedef _T ArgType;
|
|
|
|
typedef _T ResultType;
|
2015-04-18 01:35:36 +00:00
|
|
|
};
|
2015-04-18 01:50:20 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> struct BinaryNegate {
|
|
|
|
typedef typename _T::FirstArgType FirstArgType;
|
|
|
|
typedef typename _T::SecondArgType SecondArgType;
|
2015-05-03 22:44:48 +00:00
|
|
|
typedef bool ResultType;
|
2015-04-27 18:38:34 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
explicit BinaryNegate(const _T &__f): __fn(__f) {}
|
2015-04-28 17:48:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool operator()(const FirstArgType &__x,
|
|
|
|
const SecondArgType &__y) {
|
|
|
|
return !__fn(__x, __y);
|
2015-04-18 01:50:20 +00:00
|
|
|
}
|
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
_T __fn;
|
2015-04-18 01:50:20 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> struct UnaryNegate {
|
|
|
|
typedef typename _T::ArgType ArgType;
|
2015-05-03 22:44:48 +00:00
|
|
|
typedef bool ResultType;
|
2015-04-27 18:38:34 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
explicit UnaryNegate(const _T &__f): __fn(__f) {}
|
|
|
|
bool operator()(const ArgType &__x) {
|
|
|
|
return !__fn(__x);
|
2015-04-18 01:50:20 +00:00
|
|
|
}
|
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
_T __fn;
|
2015-04-18 01:50:20 +00:00
|
|
|
};
|
2015-04-18 17:36:06 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> UnaryNegate<_T> not1(const _T &__fn) {
|
|
|
|
return UnaryNegate<_T>(__fn);
|
2015-04-18 17:36:06 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> BinaryNegate<_T> not2(const _T &__fn) {
|
|
|
|
return BinaryNegate<_T>(__fn);
|
2015-04-18 17:36:06 +00:00
|
|
|
}
|
2015-04-18 18:02:44 +00:00
|
|
|
|
2015-05-10 20:57:52 +00:00
|
|
|
/* hash */
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> struct Hash;
|
2015-05-10 20:57:52 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> struct __OctaHashBase {
|
|
|
|
typedef _T ArgType;
|
2015-05-10 20:57:52 +00:00
|
|
|
typedef size_t ResultType;
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t operator()(_T __v) const {
|
|
|
|
return size_t(__v);
|
2015-05-10 20:57:52 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
#define __OCTA_HASH_BASIC(_T) template<> struct Hash<_T>: __OctaHashBase<_T> {};
|
2015-05-10 20:57:52 +00:00
|
|
|
|
|
|
|
__OCTA_HASH_BASIC(bool)
|
|
|
|
__OCTA_HASH_BASIC(char)
|
|
|
|
__OCTA_HASH_BASIC(schar)
|
|
|
|
__OCTA_HASH_BASIC(uchar)
|
|
|
|
__OCTA_HASH_BASIC(char16_t)
|
|
|
|
__OCTA_HASH_BASIC(char32_t)
|
|
|
|
__OCTA_HASH_BASIC(wchar_t)
|
|
|
|
__OCTA_HASH_BASIC(short)
|
|
|
|
__OCTA_HASH_BASIC(ushort)
|
|
|
|
__OCTA_HASH_BASIC(int)
|
|
|
|
__OCTA_HASH_BASIC(uint)
|
|
|
|
__OCTA_HASH_BASIC(long)
|
|
|
|
__OCTA_HASH_BASIC(ulong)
|
|
|
|
|
|
|
|
#undef __OCTA_HASH_BASIC
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
static inline size_t __octa_mem_hash(const void *__p, size_t __l) {
|
|
|
|
const uchar *__d = (const uchar *)__p;
|
|
|
|
size_t __h = 5381;
|
|
|
|
for (size_t __i = 0; __i < __l; ++__i) __h = ((__h << 5) + __h) ^ __d[__i];
|
|
|
|
return __h;
|
2015-05-10 20:57:52 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, size_t = sizeof(_T) / sizeof(size_t)>
|
2015-05-10 20:57:52 +00:00
|
|
|
struct __OctaScalarHash;
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> struct __OctaScalarHash<_T, 0> {
|
|
|
|
typedef _T ArgType;
|
2015-05-10 20:57:52 +00:00
|
|
|
typedef size_t ResultType;
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t operator()(_T __v) const {
|
|
|
|
union { _T __v; size_t __h; } __u;
|
|
|
|
__u.__h = 0;
|
|
|
|
__u.__v = __v;
|
|
|
|
return __u.__h;
|
2015-05-10 20:57:52 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> struct __OctaScalarHash<_T, 1> {
|
|
|
|
typedef _T ArgType;
|
2015-05-10 20:57:52 +00:00
|
|
|
typedef size_t ResultType;
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t operator()(_T __v) const {
|
|
|
|
union { _T __v; size_t __h; } __u;
|
|
|
|
__u.__v = __v;
|
|
|
|
return __u.__h;
|
2015-05-10 20:57:52 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> struct __OctaScalarHash<_T, 2> {
|
|
|
|
typedef _T ArgType;
|
2015-05-10 20:57:52 +00:00
|
|
|
typedef size_t ResultType;
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t operator()(_T __v) const {
|
|
|
|
union { _T __v; struct { size_t __h1, __h2; }; } __u;
|
|
|
|
__u.__v = __v;
|
|
|
|
return __octa_mem_hash((const void *)&__u, sizeof(__u));
|
2015-05-10 20:57:52 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> struct __OctaScalarHash<_T, 3> {
|
|
|
|
typedef _T ArgType;
|
2015-05-10 20:57:52 +00:00
|
|
|
typedef size_t ResultType;
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t operator()(_T __v) const {
|
|
|
|
union { _T __v; struct { size_t __h1, __h2, __h3; }; } __u;
|
|
|
|
__u.__v = __v;
|
|
|
|
return __octa_mem_hash((const void *)&__u, sizeof(__u));
|
2015-05-10 20:57:52 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> struct __OctaScalarHash<_T, 4> {
|
|
|
|
typedef _T ArgType;
|
2015-05-10 20:57:52 +00:00
|
|
|
typedef size_t ResultType;
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t operator()(_T __v) const {
|
|
|
|
union { _T __v; struct { size_t __h1, __h2, __h3, __h4; }; } __u;
|
|
|
|
__u.__v = __v;
|
|
|
|
return __octa_mem_hash((const void *)&__u, sizeof(__u));
|
2015-05-10 20:57:52 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<> struct Hash<llong>: __OctaScalarHash<llong> {};
|
|
|
|
template<> struct Hash<ullong>: __OctaScalarHash<ullong> {};
|
|
|
|
|
|
|
|
template<> struct Hash<float>: __OctaScalarHash<float> {
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t operator()(float __v) const {
|
|
|
|
if (__v == 0) return 0;
|
|
|
|
return __OctaScalarHash<float>::operator()(__v);
|
2015-05-10 20:57:52 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<> struct Hash<double>: __OctaScalarHash<double> {
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t operator()(double __v) const {
|
|
|
|
if (__v == 0) return 0;
|
|
|
|
return __OctaScalarHash<double>::operator()(__v);
|
2015-05-10 20:57:52 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<> struct Hash<ldouble>: __OctaScalarHash<ldouble> {
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t operator()(ldouble __v) const {
|
|
|
|
if (__v == 0) return 0;
|
2015-05-10 20:57:52 +00:00
|
|
|
#ifdef __i386__
|
2015-06-01 23:57:34 +00:00
|
|
|
union { ldouble __v; struct { size_t __h1, __h2, __h3, __h4; }; } __u;
|
|
|
|
__u.__h1 = __u.__h2 = __u.__h3 = __u.__h4 = 0;
|
|
|
|
__u.__v = __v;
|
|
|
|
return (__u.__h1 ^ __u.__h2 ^ __u.__h3 ^ __u.__h4);
|
2015-05-10 20:57:52 +00:00
|
|
|
#else
|
|
|
|
#ifdef __x86_64__
|
2015-06-01 23:57:34 +00:00
|
|
|
union { ldouble __v; struct { size_t __h1, __h2; }; } __u;
|
|
|
|
__u.__h1 = __u.__h2 = 0;
|
|
|
|
__u.__v = __v;
|
|
|
|
return (__u.__h1 ^ __u.__h2);
|
2015-05-10 20:57:52 +00:00
|
|
|
#else
|
2015-06-01 23:57:34 +00:00
|
|
|
return __OctaScalarHash<ldouble>::operator()(__v);
|
2015-05-10 20:57:52 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> struct Hash<_T *> {
|
|
|
|
typedef _T *ArgType;
|
2015-05-10 20:57:52 +00:00
|
|
|
typedef size_t ResultType;
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t operator()(_T *__v) const {
|
|
|
|
union { _T *__v; size_t __h; } __u;
|
|
|
|
__u.__v = __v;
|
|
|
|
return __octa_mem_hash((const void *)&__u, sizeof(__u));
|
2015-05-10 20:57:52 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
/* reference wrapper */
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-04-18 18:02:44 +00:00
|
|
|
struct ReferenceWrapper {
|
2015-06-01 23:57:34 +00:00
|
|
|
typedef _T type;
|
2015-04-18 18:02:44 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
ReferenceWrapper(_T &__v): __ptr(address_of(__v)) {}
|
2015-04-18 18:02:44 +00:00
|
|
|
ReferenceWrapper(const ReferenceWrapper &) = default;
|
2015-06-01 23:57:34 +00:00
|
|
|
ReferenceWrapper(_T &&) = delete;
|
2015-04-18 18:02:44 +00:00
|
|
|
|
|
|
|
ReferenceWrapper &operator=(const ReferenceWrapper &) = default;
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
operator _T &() const { return *__ptr; }
|
|
|
|
_T &get() const { return *__ptr; }
|
2015-04-18 18:02:44 +00:00
|
|
|
|
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
_T *__ptr;
|
2015-04-18 18:02:44 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
ReferenceWrapper<_T> ref(_T &__v) {
|
|
|
|
return ReferenceWrapper<_T>(__v);
|
2015-04-18 18:02:44 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
ReferenceWrapper<_T> ref(ReferenceWrapper<_T> __v) {
|
|
|
|
return ReferenceWrapper<_T>(__v);
|
2015-04-18 18:02:44 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> void ref(const _T &&) = delete;
|
2015-04-18 18:02:44 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
ReferenceWrapper<const _T> cref(const _T &__v) {
|
|
|
|
return ReferenceWrapper<_T>(__v);
|
2015-04-18 18:02:44 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
ReferenceWrapper<const _T> cref(ReferenceWrapper<_T> __v) {
|
|
|
|
return ReferenceWrapper<_T>(__v);
|
2015-04-18 18:02:44 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> void cref(const _T &&) = delete;
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
/* mem_fn */
|
2015-04-22 22:25:02 +00:00
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
template<typename, typename> struct __OctaMemTypes;
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, typename _R, typename ..._A>
|
|
|
|
struct __OctaMemTypes<_T, _R(_A...)> {
|
|
|
|
typedef _R ResultType;
|
|
|
|
typedef _T ArgType;
|
|
|
|
};
|
|
|
|
template<typename _T, typename _R, typename _A>
|
|
|
|
struct __OctaMemTypes<_T, _R(_A)> {
|
|
|
|
typedef _R ResultType;
|
|
|
|
typedef _T FirstArgType;
|
|
|
|
typedef _A SecondArgType;
|
|
|
|
};
|
|
|
|
template<typename _T, typename _R, typename ..._A>
|
|
|
|
struct __OctaMemTypes<_T, _R(_A...) const> {
|
|
|
|
typedef _R ResultType;
|
|
|
|
typedef const _T ArgType;
|
|
|
|
};
|
|
|
|
template<typename _T, typename _R, typename _A>
|
|
|
|
struct __OctaMemTypes<_T, _R(_A) const> {
|
|
|
|
typedef _R ResultType;
|
|
|
|
typedef const _T FirstArgType;
|
|
|
|
typedef _A SecondArgType;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _R, typename _T>
|
|
|
|
class __OctaMemFn: __OctaMemTypes<_T, _R> {
|
|
|
|
_R _T::*__ptr;
|
2015-04-24 17:16:35 +00:00
|
|
|
public:
|
2015-06-01 23:57:34 +00:00
|
|
|
__OctaMemFn(_R _T::*__ptr): __ptr(__ptr) {}
|
|
|
|
template<typename... _A>
|
|
|
|
auto operator()(_T &__obj, _A &&...__args) ->
|
|
|
|
decltype(((__obj).*(__ptr))(forward<_A>(__args)...)) {
|
|
|
|
return ((__obj).*(__ptr))(forward<_A>(__args)...);
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename... _A>
|
|
|
|
auto operator()(const _T &__obj, _A &&...__args) ->
|
|
|
|
decltype(((__obj).*(__ptr))(forward<_A>(__args)...)) const {
|
|
|
|
return ((__obj).*(__ptr))(forward<_A>(__args)...);
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename... _A>
|
|
|
|
auto operator()(_T *__obj, _A &&...__args) ->
|
|
|
|
decltype(((__obj)->*(__ptr))(forward<_A>(__args)...)) {
|
|
|
|
return ((__obj)->*(__ptr))(forward<_A>(__args)...);
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename... _A>
|
|
|
|
auto operator()(const _T *__obj, _A &&...__args) ->
|
|
|
|
decltype(((__obj)->*(__ptr))(forward<_A>(__args)...)) const {
|
|
|
|
return ((__obj)->*(__ptr))(forward<_A>(__args)...);
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _R, typename _T>
|
|
|
|
__OctaMemFn<_R, _T> mem_fn(_R _T:: *__ptr) {
|
|
|
|
return __OctaMemFn<_R, _T>(__ptr);
|
2015-04-22 22:25:02 +00:00
|
|
|
}
|
|
|
|
|
2015-04-22 17:42:58 +00:00
|
|
|
/* function impl
|
|
|
|
* reference: http://probablydance.com/2013/01/13/a-faster-implementation-of-stdfunction
|
|
|
|
*/
|
|
|
|
|
|
|
|
template<typename> struct Function;
|
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
struct __OctaFunctorData {
|
2015-06-01 23:57:34 +00:00
|
|
|
void *__p1, *__p2;
|
2015-04-24 17:16:35 +00:00
|
|
|
};
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-04-24 17:16:35 +00:00
|
|
|
struct __OctaFunctorInPlace {
|
2015-06-01 23:57:34 +00:00
|
|
|
static constexpr bool value = sizeof(_T) <= sizeof(__OctaFunctorData)
|
|
|
|
&& (alignof(__OctaFunctorData) % alignof(_T)) == 0
|
|
|
|
&& octa::IsMoveConstructible<_T>::value;
|
2015-04-24 17:16:35 +00:00
|
|
|
};
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, typename _E = void>
|
2015-04-24 17:16:35 +00:00
|
|
|
struct __OctaFunctorDataManager {
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _R, typename ..._A>
|
|
|
|
static _R __call(const __OctaFunctorData &__s, _A ...__args) {
|
|
|
|
return ((_T &)__s)(octa::forward<_A>(__args)...);
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
static void __store_f(__OctaFunctorData &__s, _T __v) {
|
|
|
|
new (&__get_ref(__s)) _T(octa::forward<_T>(__v));
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
static void __move_f(__OctaFunctorData &__lhs, __OctaFunctorData &&__rhs) {
|
|
|
|
new (&__get_ref(__lhs)) _T(octa::move(__get_ref(__rhs)));
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
static void __destroy_f(__OctaFunctorData &__s) {
|
|
|
|
__get_ref(__s).~_T();
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
static _T &__get_ref(const __OctaFunctorData &__s) {
|
|
|
|
return (_T &)__s;
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
|
|
|
};
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct __OctaFunctorDataManager<_T, EnableIf<!__OctaFunctorInPlace<_T>::value>> {
|
|
|
|
template<typename _R, typename ..._A>
|
|
|
|
static _R __call(const __OctaFunctorData &__s, _A ...__args) {
|
|
|
|
return (*(_T *&)__s)(octa::forward<_A>(__args)...);
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
static void __store_f(__OctaFunctorData &__s, _T __v) {
|
|
|
|
new (&__get_ptr_ref(__s)) _T *(new _T(octa::forward<_T>(__v)));
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
static void __move_f(__OctaFunctorData &__lhs, __OctaFunctorData &&__rhs) {
|
|
|
|
new (&__get_ptr_ref(__lhs)) _T *(__get_ptr_ref(__rhs));
|
|
|
|
__get_ptr_ref(__rhs) = nullptr;
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
static void __destroy_f(__OctaFunctorData &__s) {
|
|
|
|
_T *&__ptr = __get_ptr_ref(__s);
|
|
|
|
if (!__ptr) return;
|
|
|
|
delete __ptr;
|
|
|
|
__ptr = nullptr;
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
static _T &__get_ref(const __OctaFunctorData &__s) {
|
|
|
|
return *__get_ptr_ref(__s);
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
static _T *&__get_ptr_ref(__OctaFunctorData &__s) {
|
|
|
|
return (_T *&)__s;
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
static _T *&__get_ptr_ref(const __OctaFunctorData &__s) {
|
|
|
|
return (_T *&)__s;
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
|
|
|
};
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
struct __OctaFunctionManager;
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-04-27 19:23:38 +00:00
|
|
|
struct __OctaFmStorage {
|
2015-06-01 23:57:34 +00:00
|
|
|
__OctaFunctorData __data;
|
|
|
|
const __OctaFunctionManager *__manager;
|
2015-04-24 17:16:35 +00:00
|
|
|
};
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-04-24 17:16:35 +00:00
|
|
|
static const __OctaFunctionManager &__octa_get_default_fm();
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
struct __OctaFunctionManager {
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
inline static const __OctaFunctionManager __create_default_manager() {
|
2015-04-24 17:16:35 +00:00
|
|
|
return __OctaFunctionManager {
|
2015-06-01 23:57:34 +00:00
|
|
|
&__call_move_and_destroy<_T>,
|
|
|
|
&__call_copy<_T>,
|
|
|
|
&__call_destroy<_T>
|
2015-04-24 17:16:35 +00:00
|
|
|
};
|
|
|
|
}
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
void (* const __call_move_and_destroyf)(__OctaFmStorage &__lhs,
|
|
|
|
__OctaFmStorage &&__rhs);
|
|
|
|
void (* const __call_copyf)(__OctaFmStorage &__lhs,
|
|
|
|
const __OctaFmStorage &__rhs);
|
|
|
|
void (* const __call_destroyf)(__OctaFmStorage &__s);
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
static void __call_move_and_destroy(__OctaFmStorage &__lhs,
|
|
|
|
__OctaFmStorage &&__rhs) {
|
|
|
|
typedef __OctaFunctorDataManager<_T> _spec;
|
|
|
|
_spec::__move_f(__lhs.__data, octa::move(__rhs.__data));
|
|
|
|
_spec::__destroy_f(__rhs.__data);
|
|
|
|
__lhs.__manager = &__octa_get_default_fm<_T>();
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
static void __call_copy(__OctaFmStorage &__lhs,
|
|
|
|
const __OctaFmStorage &__rhs) {
|
|
|
|
typedef __OctaFunctorDataManager<_T> _spec;
|
|
|
|
__lhs.__manager = &__octa_get_default_fm<_T>();
|
|
|
|
_spec::__store_f(__lhs.__data, _spec::__get_ref(__rhs.__data));
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
static void __call_destroy(__OctaFmStorage &__s) {
|
|
|
|
typedef __OctaFunctorDataManager<_T> _spec;
|
|
|
|
_spec::__destroy_f(__s.__data);
|
2015-04-22 17:42:58 +00:00
|
|
|
}
|
2015-04-24 17:16:35 +00:00
|
|
|
};
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-04-24 17:16:35 +00:00
|
|
|
inline static const __OctaFunctionManager &__octa_get_default_fm() {
|
2015-06-01 23:57:34 +00:00
|
|
|
static const __OctaFunctionManager __def_manager
|
|
|
|
= __OctaFunctionManager::__create_default_manager<_T>();
|
|
|
|
return __def_manager;
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _R, typename...>
|
2015-04-24 17:16:35 +00:00
|
|
|
struct __OctaFunction {
|
2015-06-01 23:57:34 +00:00
|
|
|
typedef _R ResultType;
|
2015-04-24 17:16:35 +00:00
|
|
|
};
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _R, typename _T>
|
|
|
|
struct __OctaFunction<_R, _T> {
|
|
|
|
typedef _R ResultType;
|
|
|
|
typedef _T ArgType;
|
2015-04-24 17:16:35 +00:00
|
|
|
};
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _R, typename _T, typename _U>
|
|
|
|
struct __OctaFunction<_R, _T, _U> {
|
|
|
|
typedef _R ResultType;
|
|
|
|
typedef _T FirstArgType;
|
|
|
|
typedef _U SecondArgType;
|
2015-04-24 17:16:35 +00:00
|
|
|
};
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-05-03 15:09:47 +00:00
|
|
|
template<typename, typename>
|
2015-06-01 23:57:34 +00:00
|
|
|
struct __OctaIsValidFunctor {
|
2015-05-03 15:09:47 +00:00
|
|
|
static constexpr bool value = false;
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _R, typename ..._A>
|
|
|
|
struct __OctaIsValidFunctor<Function<_R(_A...)>, _R(_A...)> {
|
2015-05-03 15:09:47 +00:00
|
|
|
static constexpr bool value = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct __OctaEmpty {
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
_T __octa_func_to_functor(_T &&__f) {
|
|
|
|
return octa::forward<_T>(__f);
|
2015-05-03 15:09:47 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _RR, typename _T, typename ..._AA>
|
|
|
|
auto __octa_func_to_functor(_RR (_T::*__f)(_AA...))
|
|
|
|
-> decltype(mem_fn(__f)) {
|
|
|
|
return mem_fn(__f);
|
2015-05-03 15:09:47 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _RR, typename _T, typename ..._AA>
|
|
|
|
auto __octa_func_to_functor(_RR (_T::*__f)(_AA...) const)
|
|
|
|
-> decltype(mem_fn(__f)) {
|
|
|
|
return mem_fn(__f);
|
2015-05-03 15:09:47 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, typename _R, typename ..._A>
|
|
|
|
struct __OctaIsValidFunctor<_T, _R(_A...)> {
|
|
|
|
template<typename _U>
|
|
|
|
static decltype(__octa_func_to_functor(octa::declval<_U>())
|
|
|
|
(octa::declval<_A>()...)) __test(_U *);
|
2015-05-03 15:09:47 +00:00
|
|
|
template<typename>
|
2015-06-01 23:57:34 +00:00
|
|
|
static __OctaEmpty __test(...);
|
2015-05-03 15:09:47 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
static constexpr bool value = octa::IsConvertible<
|
|
|
|
decltype(__test<_T>(nullptr)), _R
|
2015-05-03 15:09:47 +00:00
|
|
|
>::value;
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _R, typename ..._A>
|
|
|
|
struct Function<_R(_A...)>: __OctaFunction<_R, _A...> {
|
|
|
|
Function( ) { __init_empty(); }
|
|
|
|
Function(nullptr_t) { __init_empty(); }
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
Function(Function &&__f) {
|
|
|
|
__init_empty();
|
|
|
|
swap(__f);
|
2015-04-22 17:42:58 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
Function(const Function &__f): __call(__f.__call) {
|
|
|
|
__f.__stor.__manager->__call_copyf(__stor, __f.__stor);
|
2015-04-22 17:42:58 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
Function(_T __f, EnableIf<__OctaIsValidFunctor<_T, _R(_A...)>::value, __OctaEmpty>
|
2015-05-20 21:05:41 +00:00
|
|
|
= __OctaEmpty()) {
|
2015-06-01 23:57:34 +00:00
|
|
|
if (__func_is_null(__f)) {
|
|
|
|
__init_empty();
|
2015-04-22 17:42:58 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
__initialize(__octa_func_to_functor(octa::forward<_T>(__f)));
|
2015-04-22 17:42:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
~Function() {
|
2015-06-01 23:57:34 +00:00
|
|
|
__stor.__manager->__call_destroyf(__stor);
|
2015-04-22 17:42:58 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
Function &operator=(Function &&__f) {
|
|
|
|
__stor.__manager->__call_destroyf(__stor);
|
|
|
|
swap(__f);
|
2015-04-22 17:42:58 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
Function &operator=(const Function &__f) {
|
|
|
|
__stor.__manager->__call_destroyf(__stor);
|
|
|
|
__f.__stor.__manager->__call_copyf(__stor, __f.__stor);
|
2015-04-22 17:42:58 +00:00
|
|
|
return *this;
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_R operator()(_A ...__args) const {
|
|
|
|
return __call(__stor.__data, octa::forward<_A>(__args)...);
|
2015-04-22 17:42:58 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _F> void assign(_F &&__f) {
|
|
|
|
Function(octa::forward<_F>(__f)).swap(*this);
|
2015-04-22 17:42:58 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
void swap(Function &__f) {
|
|
|
|
__OctaFmStorage __tmp;
|
|
|
|
__f.__stor.__manager->__call_move_and_destroyf(__tmp,
|
|
|
|
octa::move(__f.__stor));
|
|
|
|
__stor.__manager->__call_move_and_destroyf(__f.__stor,
|
|
|
|
octa::move(__stor));
|
|
|
|
__tmp.__manager->__call_move_and_destroyf(__stor,
|
|
|
|
octa::move(__tmp));
|
|
|
|
octa::swap(__call, __f.__call);
|
2015-04-22 17:42:58 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
operator bool() const { return __call != nullptr; }
|
2015-04-22 17:42:58 +00:00
|
|
|
|
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
__OctaFmStorage __stor;
|
|
|
|
_R (*__call)(const __OctaFunctorData &, _A...);
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
void __initialize(_T __f) {
|
|
|
|
__call = &__OctaFunctorDataManager<_T>::template __call<_R, _A...>;
|
|
|
|
__stor.__manager = &__octa_get_default_fm<_T>();
|
|
|
|
__OctaFunctorDataManager<_T>::__store_f(__stor.__data,
|
|
|
|
octa::forward<_T>(__f));
|
2015-04-22 17:42:58 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
void __init_empty() {
|
|
|
|
typedef _R(*__emptyf)(_A...);
|
|
|
|
__call = nullptr;
|
|
|
|
__stor.__manager = &__octa_get_default_fm<__emptyf>();
|
|
|
|
__OctaFunctorDataManager<__emptyf>::__store_f(__stor.__data, nullptr);
|
2015-04-22 17:42:58 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
static bool __func_is_null(const _T &) { return false; }
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
static bool __func_is_null(_R (* const &__fptr)(_A...)) {
|
|
|
|
return __fptr == nullptr;
|
2015-04-22 17:42:58 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _RR, typename _T, typename ..._AA>
|
|
|
|
static bool __func_is_null(_RR (_T::* const &__fptr)(_AA...)) {
|
|
|
|
return __fptr == nullptr;
|
2015-04-22 17:42:58 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _RR, typename _T, typename ..._AA>
|
|
|
|
static bool __func_is_null(_RR (_T::* const &__fptr)(_AA...) const) {
|
|
|
|
return __fptr == nullptr;
|
2015-04-22 17:42:58 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
bool operator==(nullptr_t, const Function<_T> &__rhs) { return !__rhs; }
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
bool operator==(const Function<_T> &__lhs, nullptr_t) { return !__lhs; }
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
bool operator!=(nullptr_t, const Function<_T> &__rhs) { return __rhs; }
|
2015-04-22 17:42:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
bool operator!=(const Function<_T> &__lhs, nullptr_t) { return __lhs; }
|
2015-04-18 01:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|