diff options
Diffstat (limited to 'ml/dlib/dlib/bound_function_pointer/bound_function_pointer_kernel_1.h')
-rw-r--r-- | ml/dlib/dlib/bound_function_pointer/bound_function_pointer_kernel_1.h | 774 |
1 files changed, 774 insertions, 0 deletions
diff --git a/ml/dlib/dlib/bound_function_pointer/bound_function_pointer_kernel_1.h b/ml/dlib/dlib/bound_function_pointer/bound_function_pointer_kernel_1.h new file mode 100644 index 000000000..a39592742 --- /dev/null +++ b/ml/dlib/dlib/bound_function_pointer/bound_function_pointer_kernel_1.h @@ -0,0 +1,774 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_BOUND_FUNCTION_POINTER_KERNEl_1_ +#define DLIB_BOUND_FUNCTION_POINTER_KERNEl_1_ + +#include "../algs.h" +#include "../member_function_pointer.h" +#include "bound_function_pointer_kernel_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + namespace bfp1_helpers + { + template <typename T> struct strip { typedef T type; }; + template <typename T> struct strip<T&> { typedef T type; }; + + // ------------------------------------------------------------------------------------ + + class bound_function_helper_base_base + { + public: + virtual ~bound_function_helper_base_base(){} + virtual void call() const = 0; + virtual bool is_set() const = 0; + virtual void clone(void* ptr) const = 0; + }; + + // ------------------------------------------------------------------------------------ + + template <typename T1, typename T2, typename T3, typename T4> + class bound_function_helper_base : public bound_function_helper_base_base + { + public: + bound_function_helper_base():arg1(0), arg2(0), arg3(0), arg4(0) {} + + typename strip<T1>::type* arg1; + typename strip<T2>::type* arg2; + typename strip<T3>::type* arg3; + typename strip<T4>::type* arg4; + + + member_function_pointer<T1,T2,T3,T4> mfp; + }; + + // ---------------- + + template <typename F, typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void> + class bound_function_helper : public bound_function_helper_base<T1,T2,T3,T4> + { + public: + void call() const + { + (*fp)(*this->arg1, *this->arg2, *this->arg3, *this->arg4); + } + + typename strip<F>::type* fp; + }; + + template <typename T1, typename T2, typename T3, typename T4> + class bound_function_helper<void,T1,T2,T3,T4> : public bound_function_helper_base<T1,T2,T3,T4> + { + public: + void call() const + { + if (this->mfp) this->mfp(*this->arg1, *this->arg2, *this->arg3, *this->arg4); + else if (fp) fp(*this->arg1, *this->arg2, *this->arg3, *this->arg4); + } + + void (*fp)(T1, T2, T3, T4); + }; + + // ---------------- + + template <typename F> + class bound_function_helper<F,void,void,void,void> : public bound_function_helper_base<void,void,void,void> + { + public: + void call() const + { + (*fp)(); + } + + typename strip<F>::type* fp; + }; + + template <> + class bound_function_helper<void,void,void,void,void> : public bound_function_helper_base<void,void,void,void> + { + public: + void call() const + { + if (this->mfp) this->mfp(); + else if (fp) fp(); + } + + void (*fp)(); + }; + + // ---------------- + + template <typename F, typename T1> + class bound_function_helper<F,T1,void,void,void> : public bound_function_helper_base<T1,void,void,void> + { + public: + void call() const + { + (*fp)(*this->arg1); + } + + typename strip<F>::type* fp; + }; + + template <typename T1> + class bound_function_helper<void,T1,void,void,void> : public bound_function_helper_base<T1,void,void,void> + { + public: + void call() const + { + if (this->mfp) this->mfp(*this->arg1); + else if (fp) fp(*this->arg1); + } + + void (*fp)(T1); + }; + + // ---------------- + + template <typename F, typename T1, typename T2> + class bound_function_helper<F,T1,T2,void,void> : public bound_function_helper_base<T1,T2,void,void> + { + public: + void call() const + { + (*fp)(*this->arg1, *this->arg2); + } + + typename strip<F>::type* fp; + }; + + template <typename T1, typename T2> + class bound_function_helper<void,T1,T2,void,void> : public bound_function_helper_base<T1,T2,void,void> + { + public: + void call() const + { + if (this->mfp) this->mfp(*this->arg1, *this->arg2); + else if (fp) fp(*this->arg1, *this->arg2); + } + + void (*fp)(T1, T2); + }; + + // ---------------- + + template <typename F, typename T1, typename T2, typename T3> + class bound_function_helper<F,T1,T2,T3,void> : public bound_function_helper_base<T1,T2,T3,void> + { + public: + void call() const + { + (*fp)(*this->arg1, *this->arg2, *this->arg3); + } + + typename strip<F>::type* fp; + }; + + template <typename T1, typename T2, typename T3> + class bound_function_helper<void,T1,T2,T3,void> : public bound_function_helper_base<T1,T2,T3,void> + { + public: + + void call() const + { + if (this->mfp) this->mfp(*this->arg1, *this->arg2, *this->arg3); + else if (fp) fp(*this->arg1, *this->arg2, *this->arg3); + } + + void (*fp)(T1, T2, T3); + }; + + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + + template <typename T> + class bound_function_helper_T : public T + { + public: + bound_function_helper_T(){ this->fp = 0;} + + bool is_set() const + { + return this->fp != 0 || this->mfp.is_set(); + } + + template <unsigned long mem_size> + void safe_clone(stack_based_memory_block<mem_size>& buf) + { + // This is here just to validate the assumption that our block of memory we have made + // in bf_memory is the right size to store the data for this object. If you + // get a compiler error on this line then email me :) + COMPILE_TIME_ASSERT(sizeof(bound_function_helper_T) <= mem_size); + clone(buf.get()); + } + + void clone (void* ptr) const + { + bound_function_helper_T* p = new(ptr) bound_function_helper_T(); + p->arg1 = this->arg1; + p->arg2 = this->arg2; + p->arg3 = this->arg3; + p->arg4 = this->arg4; + p->fp = this->fp; + p->mfp = this->mfp; + } + }; + + } + +// ---------------------------------------------------------------------------------------- + + class bound_function_pointer + { + typedef bfp1_helpers::bound_function_helper_T<bfp1_helpers::bound_function_helper<void,int> > bf_null_type; + + public: + + // These typedefs are here for backwards compatibility with previous versions of + // dlib. + typedef bound_function_pointer kernel_1a; + typedef bound_function_pointer kernel_1a_c; + + + bound_function_pointer ( + ) { bf_null_type().safe_clone(bf_memory); } + + bound_function_pointer ( + const bound_function_pointer& item + ) { item.bf()->clone(bf_memory.get()); } + + ~bound_function_pointer() + { destroy_bf_memory(); } + + bound_function_pointer& operator= ( + const bound_function_pointer& item + ) { bound_function_pointer(item).swap(*this); return *this; } + + void clear ( + ) { bound_function_pointer().swap(*this); } + + bool is_set ( + ) const + { + return bf()->is_set(); + } + + void swap ( + bound_function_pointer& item + ) + { + // make a temp copy of item + bound_function_pointer temp(item); + + // destory the stuff in item + item.destroy_bf_memory(); + // copy *this into item + bf()->clone(item.bf_memory.get()); + + // destory the stuff in this + destroy_bf_memory(); + // copy temp into *this + temp.bf()->clone(bf_memory.get()); + } + + void operator() ( + ) const + { + // make sure requires clause is not broken + DLIB_ASSERT(is_set() == true , + "\tvoid bound_function_pointer::operator()" + << "\n\tYou must call set() before you can use this function" + << "\n\tthis: " << this + ); + + bf()->call(); + } + + private: + struct dummy{ void nonnull() {}}; + typedef void (dummy::*safe_bool)(); + + public: + operator safe_bool () const { return is_set() ? &dummy::nonnull : 0; } + bool operator!() const { return !is_set(); } + + // ------------------------------------------- + // set function object overloads + // ------------------------------------------- + + template <typename F> + void set ( + F& function_object + ) + { + COMPILE_TIME_ASSERT(is_function<F>::value == false); + COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false); + + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<F> > bf_helper_type; + + bf_helper_type temp; + temp.fp = &function_object; + + temp.safe_clone(bf_memory); + } + + template <typename F, typename A1 > + void set ( + F& function_object, + A1& arg1 + ) + { + COMPILE_TIME_ASSERT(is_function<F>::value == false); + COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false); + + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<F,A1> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.fp = &function_object; + + temp.safe_clone(bf_memory); + } + + template <typename F, typename A1, typename A2 > + void set ( + F& function_object, + A1& arg1, + A2& arg2 + ) + { + COMPILE_TIME_ASSERT(is_function<F>::value == false); + COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false); + + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<F,A1,A2> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.fp = &function_object; + + temp.safe_clone(bf_memory); + } + + template <typename F, typename A1, typename A2, typename A3 > + void set ( + F& function_object, + A1& arg1, + A2& arg2, + A3& arg3 + ) + { + COMPILE_TIME_ASSERT(is_function<F>::value == false); + COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false); + + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<F,A1,A2,A3> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.fp = &function_object; + + temp.safe_clone(bf_memory); + } + + template <typename F, typename A1, typename A2, typename A3, typename A4> + void set ( + F& function_object, + A1& arg1, + A2& arg2, + A3& arg3, + A4& arg4 + ) + { + COMPILE_TIME_ASSERT(is_function<F>::value == false); + COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false); + + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<F,A1,A2,A3,A4> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.arg4 = &arg4; + temp.fp = &function_object; + + temp.safe_clone(bf_memory); + } + + // ------------------------------------------- + // set mfp overloads + // ------------------------------------------- + + template <typename T> + void set ( + T& object, + void (T::*funct)() + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void> > bf_helper_type; + + bf_helper_type temp; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + template <typename T > + void set ( + const T& object, + void (T::*funct)()const + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void> > bf_helper_type; + + bf_helper_type temp; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + // ------------------------------------------- + + template <typename T, typename T1, typename A1 > + void set ( + T& object, + void (T::*funct)(T1), + A1& arg1 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void,T1> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + template <typename T, typename T1, typename A1 > + void set ( + const T& object, + void (T::*funct)(T1)const, + A1& arg1 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void,T1> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + // ---------------- + + template <typename T, typename T1, typename A1, + typename T2, typename A2> + void set ( + T& object, + void (T::*funct)(T1, T2), + A1& arg1, + A2& arg2 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void,T1,T2> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + template <typename T, typename T1, typename A1, + typename T2, typename A2> + void set ( + const T& object, + void (T::*funct)(T1, T2)const, + A1& arg1, + A2& arg2 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void,T1,T2> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + // ---------------- + + template <typename T, typename T1, typename A1, + typename T2, typename A2, + typename T3, typename A3> + void set ( + T& object, + void (T::*funct)(T1, T2, T3), + A1& arg1, + A2& arg2, + A3& arg3 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void,T1,T2,T3> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + template <typename T, typename T1, typename A1, + typename T2, typename A2, + typename T3, typename A3> + void set ( + const T& object, + void (T::*funct)(T1, T2, T3)const, + A1& arg1, + A2& arg2, + A3& arg3 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void,T1,T2,T3> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + // ---------------- + + template <typename T, typename T1, typename A1, + typename T2, typename A2, + typename T3, typename A3, + typename T4, typename A4> + void set ( + T& object, + void (T::*funct)(T1, T2, T3, T4), + A1& arg1, + A2& arg2, + A3& arg3, + A4& arg4 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void,T1,T2,T3,T4> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.arg4 = &arg4; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + template <typename T, typename T1, typename A1, + typename T2, typename A2, + typename T3, typename A3, + typename T4, typename A4> + void set ( + const T& object, + void (T::*funct)(T1, T2, T3, T4)const, + A1& arg1, + A2& arg2, + A3& arg3, + A4& arg4 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void,T1,T2,T3,T4> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.arg4 = &arg4; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + // ------------------------------------------- + // set fp overloads + // ------------------------------------------- + + void set ( + void (*funct)() + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void> > bf_helper_type; + + bf_helper_type temp; + temp.fp = funct; + + temp.safe_clone(bf_memory); + } + + template <typename T1, typename A1> + void set ( + void (*funct)(T1), + A1& arg1 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void,T1> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.fp = funct; + + temp.safe_clone(bf_memory); + } + + template <typename T1, typename A1, + typename T2, typename A2> + void set ( + void (*funct)(T1, T2), + A1& arg1, + A2& arg2 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void,T1,T2> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.fp = funct; + + temp.safe_clone(bf_memory); + } + + template <typename T1, typename A1, + typename T2, typename A2, + typename T3, typename A3> + void set ( + void (*funct)(T1, T2, T3), + A1& arg1, + A2& arg2, + A3& arg3 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void,T1,T2,T3> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.fp = funct; + + temp.safe_clone(bf_memory); + } + + template <typename T1, typename A1, + typename T2, typename A2, + typename T3, typename A3, + typename T4, typename A4> + void set ( + void (*funct)(T1, T2, T3, T4), + A1& arg1, + A2& arg2, + A3& arg3, + A4& arg4 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T<bound_function_helper<void,T1,T2,T3,T4> > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.arg4 = &arg4; + temp.fp = funct; + + temp.safe_clone(bf_memory); + } + + // ------------------------------------------- + + private: + + stack_based_memory_block<sizeof(bf_null_type)> bf_memory; + + void destroy_bf_memory ( + ) + { + // Honestly, this probably doesn't even do anything but I'm putting + // it here just for good measure. + bf()->~bound_function_helper_base_base(); + } + + bfp1_helpers::bound_function_helper_base_base* bf () + { return static_cast<bfp1_helpers::bound_function_helper_base_base*>(bf_memory.get()); } + + const bfp1_helpers::bound_function_helper_base_base* bf () const + { return static_cast<const bfp1_helpers::bound_function_helper_base_base*>(bf_memory.get()); } + + }; + +// ---------------------------------------------------------------------------------------- + + inline void swap ( + bound_function_pointer& a, + bound_function_pointer& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_BOUND_FUNCTION_POINTER_KERNEl_1_ + |