Commit 55aa4367 authored by Davis King's avatar Davis King

Added the bound_function_pointer object.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402669
parent 1e6a2f15
// Copyright (C) 2008 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BOUND_FUNCTION_POINTEr_
#define DLIB_BOUND_FUNCTION_POINTEr_
#include "bound_function_pointer/bound_function_pointer_kernel_1.h"
#include "bound_function_pointer/bound_function_pointer_kernel_c.h"
namespace dlib
{
class bound_function_pointer
{
bound_function_pointer() {}
public:
//----------- kernels ---------------
// kernel_1a
typedef bound_function_pointer_kernel_1
kernel_1a;
typedef bound_function_pointer_kernel_c<kernel_1a>
kernel_1a_c;
};
}
#endif // DLIB_BOUND_FUNCTION_POINTEr_
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.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"
namespace dlib
{
// ----------------------------------------------------------------------------------------
namespace bfp1_helpers
{
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:
template <typename T> struct strip { typedef T type; };
template <typename T> struct strip<T&> { typedef T type; };
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;
typename member_function_pointer<T1,T2,T3,T4>::kernel_1a_c mfp;
};
template <typename T1, 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
{
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 T1>
class bound_function_helper<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 T1, typename T2>
class bound_function_helper<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 T1, typename T2, typename T3>
class bound_function_helper<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(char (&buf)[mem_size])
{
// This is here just to validate the assumption that our block of memory we have made
// in bf_memory.data 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);
}
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_kernel_1
{
typedef bfp1_helpers::bound_function_helper_T<bfp1_helpers::bound_function_helper<int> > bf_null_type;
public:
bound_function_pointer_kernel_1 (
) { bf_null_type().safe_clone(bf_memory.data); }
bound_function_pointer_kernel_1 (
const bound_function_pointer_kernel_1& item
) { item.bf()->clone(bf_memory.data); }
~bound_function_pointer_kernel_1()
{ destroy_bf_memory(); }
bound_function_pointer_kernel_1& operator= (
const bound_function_pointer_kernel_1& item
) { bound_function_pointer_kernel_1(item).swap(*this); return *this; }
void clear (
) { bound_function_pointer_kernel_1().swap(*this); }
bool is_set (
) const
{
return bf()->is_set();
}
void swap (
bound_function_pointer_kernel_1& item
)
{
// make a temp copy of item
bound_function_pointer_kernel_1 temp(item);
// destory the stuff in item
item.destroy_bf_memory();
// copy *this into item
bf()->clone(item.bf_memory.data);
// destory the stuff in this
destroy_bf_memory();
// copy temp into *this
temp.bf()->clone(bf_memory.data);
}
void operator() (
) const
{
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 mfp overloads
// -------------------------------------------
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<T1> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.mfp.set(object,funct);
temp.safe_clone(bf_memory.data);
}
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<T1> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.mfp.set(object,funct);
temp.safe_clone(bf_memory.data);
}
// ----------------
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<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.data);
}
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<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.data);
}
// ----------------
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<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.data);
}
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<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.data);
}
// ----------------
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<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.data);
}
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<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.data);
}
// -------------------------------------------
// set fp overloads
// -------------------------------------------
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<T1> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.fp = funct;
temp.safe_clone(bf_memory.data);
}
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<T1,T2> > bf_helper_type;
bf_helper_type temp;
temp.arg1 = &arg1;
temp.arg2 = &arg2;
temp.fp = funct;
temp.safe_clone(bf_memory.data);
}
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<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.data);
}
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<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.data);
}
// -------------------------------------------
private:
union data_block_type
{
// All of this garbage is to make sure this union is properly aligned
// (a union is always aligned such that everything in it would be properly
// aligned. So the assumption here is that one of these things big good
// alignment to satisfy mp_null_impl objects (or other objects like it).
void* void_ptr;
long double dtemp;
struct {
void (bfp1_helpers::bound_function_helper_base_base::*callback)();
bfp1_helpers::bound_function_helper_base_base* o;
} stuff;
char data[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 ()
{ void* ptr = bf_memory.data; return static_cast<bfp1_helpers::bound_function_helper_base_base*>(ptr); }
const bfp1_helpers::bound_function_helper_base_base* bf () const
{ const void* ptr = bf_memory.data; return static_cast<const bfp1_helpers::bound_function_helper_base_base*>(ptr); }
};
// ----------------------------------------------------------------------------------------
inline void swap (
bound_function_pointer_kernel_1& a,
bound_function_pointer_kernel_1& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BOUND_FUNCTION_POINTER_KERNEl_1_
// Copyright (C) 2008 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BOUND_FUNCTION_POINTER_KERNEl_ABSTRACT_
#ifdef DLIB_BOUND_FUNCTION_POINTER_KERNEl_ABSTRACT_
namespace dlib
{
// ----------------------------------------------------------------------------------------
class bound_function_pointer
{
/*!
INITIAL VALUE
is_set() == false
WHAT THIS OBJECT REPRESENTS
This object represents a function with all its arguments bound to
specific objects. For example:
void test(int& var) { var = var+1; }
bound_function_pointer funct;
int a = 4;
funct.set(test,a); // bind the variable a to the first argument of the test() function
// at this point a == 4
funct();
// after funct() is called a == 5
!*/
public:
bound_function_pointer (
);
/*!
ensures
- #*this is properly initialized
!*/
bound_function_pointer(
const bound_function_pointer& item
);
/*!
ensures
- *this == item
!*/
~bound_function_pointer (
);
/*!
ensures
- any resources associated with *this have been released
!*/
bound_function_pointer& operator=(
const bound_function_pointer& item
);
/*!
ensures
- *this == item
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
!*/
bool is_set (
) const;
/*!
ensures
- if (this->set() has been called) then
- returns true
- else
- returns false
!*/
operator some_undefined_pointer_type (
) const;
/*!
ensures
- if (is_set()) then
- returns a non 0 value
- else
- returns a 0 value
!*/
bool operator! (
) const;
/*!
ensuresobject.*
- returns !is_set()
!*/
void operator () (
) const;
/*!
requires
- is_set() == true
ensures
- calls the bound function on the object specified by the last
call to this->set()
throws
- any exception thrown by the function specified by
the previous call to this->set().
If any of these exceptions are thrown then the call to this
function will have no effect on *this.
!*/
void swap (
bound_function_pointer& item
);
/*!
ensures
- swaps *this and item
!*/
// ----------------------
template < typename T, typename T1, typename A1 >
void set (
T& object,
void (T::*funct)(T1),
A1& arg1
);
/*!
requires
- funct == a valid member function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1)
!*/
template < typename T, typename T1, typename A1 >
void set (
const T& object,
void (T::*funct)(T1)const,
A1& arg1
);
/*!
requires
- funct == a valid bound function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1)
!*/
template <typename T1, typename A1>
void set (
void (*funct)(T1),
A1& arg1
);
/*!
requires
- funct == a valid function pointer
ensures
- #is_set() == true
- calls to this->operator() will call funct(arg1)
!*/
// ----------------------
template < typename T, typename T1, typename A1
typename T2, typename A2>
void set (
T& object,
void (T::*funct)(T1,T2),
A1& arg1,
A2& arg2
);
/*!
requires
- funct == a valid member function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1,arg2)
!*/
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
);
/*!
requires
- funct == a valid bound function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1,arg2)
!*/
template <typename T1, typename A1,
typename T2, typename A2>
void set (
void (*funct)(T1,T2),
A1& arg1,
A2& arg2
);
/*!
requires
- funct == a valid function pointer
ensures
- #is_set() == true
- calls to this->operator() will call funct(arg1,arg2)
!*/
// ----------------------
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
);
/*!
requires
- funct == a valid member function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1,arg2,arg3)
!*/
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
);
/*!
requires
- funct == a valid bound function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1,arg2,arg3)
!*/
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
);
/*!
requires
- funct == a valid function pointer
ensures
- #is_set() == true
- calls to this->operator() will call funct(arg1,arg2,arg3)
!*/
// ----------------------
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
);
/*!
requires
- funct == a valid member function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1,arg2,arg3,arg4)
!*/
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
);
/*!
requires
- funct == a valid bound function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*funct)(arg1,arg2,arg3,arg4)
!*/
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
);
/*!
requires
- funct == a valid function pointer
ensures
- #is_set() == true
- calls to this->operator() will call funct(arg1,arg2,arg3,arg4)
!*/
};
// ----------------------------------------------------------------------------------------
inline void swap (
bound_function_pointer& a,
bound_function_pointer& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BOUND_FUNCTION_POINTER_KERNEl_ABSTRACT_
// Copyright (C) 2008 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BOUND_FUNCTION_POINTER_KERNEl_C_
#define DLIB_BOUND_FUNCTION_POINTER_KERNEl_C_
#include "bound_function_pointer_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
namespace dlib
{
template <
typename bound_function_pointer_base // is an implementation of bound_function_pointer_kernel_abstract.h
>
class bound_function_pointer_kernel_c : public bound_function_pointer_base
{
public:
void operator () (
) const;
};
template <
typename bound_function_pointer_base
>
inline void swap (
bound_function_pointer_kernel_c<bound_function_pointer_base>& a,
bound_function_pointer_kernel_c<bound_function_pointer_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename bound_function_pointer_base
>
void bound_function_pointer_kernel_c<bound_function_pointer_base>::
operator() (
) const
{
// make sure requires clause is not broken
DLIB_CASSERT(this->is_set() == true ,
"\tvoid bound_function_pointer::operator()"
<< "\n\tYou must call set() before you can use this function"
<< "\n\tthis: " << this
);
// call the real function
bound_function_pointer_base::operator()();
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BOUND_FUNCTION_POINTER_KERNEl_C_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment