Commit 72d9adbf authored by Davis King's avatar Davis King

Changed the member function pointer object so that:

   - It never calls new or delete
   - It can point to const member functions
   - It has an operator bool and operator! so that it can now
     be used in an if statement like a normal pointer

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402614
parent 7016a876
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "../algs.h" #include "../algs.h"
#include "member_function_pointer_kernel_abstract.h" #include "member_function_pointer_kernel_abstract.h"
#include <new>
namespace dlib namespace dlib
{ {
...@@ -19,323 +20,254 @@ namespace dlib ...@@ -19,323 +20,254 @@ namespace dlib
> >
class member_function_pointer_kernel_1; class member_function_pointer_kernel_1;
template <
typename PARAM1,
typename PARAM2,
typename PARAM3,
typename PARAM4
>
void swap (
member_function_pointer_kernel_1<PARAM1,PARAM2,PARAM3,PARAM4>& a,
member_function_pointer_kernel_1<PARAM1,PARAM2,PARAM3,PARAM4>& b
) { a.swap(b); }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <> class mfp_kernel_1_base_class
class member_function_pointer_kernel_1<void,void,void,void>
{ {
/*! /*
INITIAL VALUE All member function pointer classes inherit from this class. This
- mp == 0 is where most of the things in a member function pointer are defined.
*/
CONVENTION protected:
- is_set() == (mp != 0) enum mfp_type { mfp_nonconst, mfp_const, mfp_null};
Note that I'm using reinterpret_cast rather than dynamic_cast here class mp_base_base
in the is_same() function. It would be better if dynamic_cast was used
but some compilers don't enable RTTI by default so using it would make the
build process more complicated for users so I'm not using it. I'm
not aware of any platforms/compilers where reinterpret_cast won't end
up doing the right thing for us here so it should be ok.
!*/
class mp_base
{ {
public: public:
virtual ~mp_base(){} mp_base_base(void* ptr, mfp_type type_) : o(ptr),type(type_) {}
virtual void call() const = 0; virtual ~mp_base_base(){}
virtual mp_base* clone() const = 0; virtual void clone(void* ptr) const = 0;
virtual bool is_same (const mp_base* item) const = 0; virtual bool is_same (const mp_base_base* item) const = 0;
bool is_set () const { return o!=0; }
void* const o;
const mfp_type type;
}; };
template <typename T> template <typename T>
class mp_impl : public mp_base class mp_null : public mp_base_base
{ {
public: public:
mp_impl ( typedef void (T::*mfp_pointer_type)() ;
T& object,
void (T::*cb)()
) :
callback(cb),
o(&object)
{
}
void call ( mp_null (void* , mfp_pointer_type ) : mp_base_base(0,mfp_null), callback(0) {}
) const mp_null () : mp_base_base(0,mfp_null), callback(0) {}
{
(o->*callback)();
}
mp_base* clone() const { return new mp_impl(*o,callback); } const mfp_pointer_type callback;
};
bool is_same (const mp_base* item) const template <typename mp_impl>
class mp_impl_T : public mp_impl
{
/*
This class supplies the implementations clone() and is_same() for any
classes that inherit from mp_base_base. It does this in a very
roundabout way...
*/
public:
typedef typename mp_impl::mfp_pointer_type mfp_pointer_type;
mp_impl_T() : mp_impl(0,0) {}
mp_impl_T(void* ptr, mfp_pointer_type cb) : mp_impl(ptr,cb) {}
void clone (void* ptr) const { new(ptr) mp_impl_T(this->o,this->callback); }
bool is_same (const mp_base_base* item) const
{ {
const mp_impl* i = reinterpret_cast<const mp_impl*>(item); if (item->o == 0 && this->o == 0)
return (i != 0 && i->o == o && i->callback == callback); {
return true;
}
else if (item->o == this->o && this->type == item->type)
{
const mp_impl* i = reinterpret_cast<const mp_impl*>(item);
return (i->callback == this->callback);
}
return false;
} }
private:
void (T::*callback)();
T* o;
}; };
public: struct dummy { void nonnull() {}; };
typedef void param1_type;
typedef void param2_type;
typedef void param3_type;
typedef void param4_type;
member_function_pointer_kernel_1 (
) :
mp(0)
{}
member_function_pointer_kernel_1( typedef mp_impl_T<mp_null<dummy> > mp_null_impl;
const member_function_pointer_kernel_1& item public:
) :
mp(0)
{
if (item.is_set())
mp = item.mp->clone();
}
member_function_pointer_kernel_1& operator=( mfp_kernel_1_base_class (
const member_function_pointer_kernel_1& item const mfp_kernel_1_base_class& item
) ) { item.mp()->clone(mp_memory.data); }
{
if (this != &item)
{
clear();
if (item.is_set()) mfp_kernel_1_base_class (
mp = item.mp->clone(); ) { mp_null_impl().clone(mp_memory.data); }
}
return *this;
}
bool operator == ( bool operator == (
const member_function_pointer_kernel_1& item const mfp_kernel_1_base_class& item
) const ) const { return mp()->is_same(item.mp()); }
{
if (is_set() != item.is_set())
return false;
if (is_set() == false)
return true;
return mp->is_same(item.mp);
}
bool operator != ( bool operator != (
const member_function_pointer_kernel_1& item const mfp_kernel_1_base_class& item
) const { return !(*this == item); } ) const { return !(*this == item); }
~member_function_pointer_kernel_1 ( mfp_kernel_1_base_class& operator= (
) const mfp_kernel_1_base_class& item
{ ) { mfp_kernel_1_base_class(item).swap(*this); return *this; }
if (mp)
delete mp; ~mfp_kernel_1_base_class (
} ) { mp()->~mp_base_base(); }
void clear( void clear(
) ) { mfp_kernel_1_base_class().swap(*this); }
{
if (mp)
{
delete mp;
mp = 0;
}
}
bool is_set ( bool is_set (
) const { return mp != 0; } ) const { return mp()->is_set(); }
template <
typename T
>
void set (
T& object,
void (T::*cb)()
)
{
clear();
mp = new mp_impl<T>(object,cb);
}
void operator () ( private:
) const { mp->call(); } typedef void (dummy::*safe_bool)();
public:
operator safe_bool () const { return is_set() ? &dummy::nonnull : 0; }
bool operator!() const { return !is_set(); }
void swap ( void swap (
member_function_pointer_kernel_1& item mfp_kernel_1_base_class& item
) { exchange(mp,item.mp); } )
{
// make a temp copy of item
mfp_kernel_1_base_class temp(item);
// copy *this into item
mp()->clone(item.mp_memory.data);
// copy temp into *this
temp.mp()->clone(mp_memory.data);
}
private: protected:
mp_base* mp; // make a block of memory big enough to hold a mp_null object.
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;
struct {
void (mp_base_base::*callback)();
mp_base_base* o;
} stuff;
char data[sizeof(mp_null_impl)];
} mp_memory;
}; mp_base_base* mp () { void* ptr = mp_memory.data; return static_cast<mp_base_base*>(ptr); }
const mp_base_base* mp () const { const void* ptr = mp_memory.data; return static_cast<const mp_base_base*>(ptr); }
};
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < template <>
typename PARAM1 class member_function_pointer_kernel_1<void,void,void,void> : public mfp_kernel_1_base_class
>
class member_function_pointer_kernel_1<PARAM1,void,void,void>
{ {
/*! class mp_base : public mp_base_base {
INITIAL VALUE
- mp == 0
CONVENTION
- is_set() == (mp != 0)
!*/
class mp_base
{
public: public:
virtual ~mp_base(){} mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {}
virtual void call(PARAM1) const = 0; virtual void call() const = 0;
virtual mp_base* clone() const = 0;
virtual bool is_same (const mp_base* item) const = 0;
}; };
template <typename T> template <typename T>
class mp_impl : public mp_base class mp_impl : public mp_base {
{
public: public:
mp_impl ( typedef void (T::*mfp_pointer_type)() ;
T& object, void call () const { (static_cast<T*>(this->o)->*callback)(); }
void (T::*cb)(PARAM1)
) :
callback(cb),
o(&object)
{
}
void call (
PARAM1 param1
) const
{
(o->*callback)(param1);
}
mp_base* clone() const { return new mp_impl(*o,callback); } mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {}
const mfp_pointer_type callback;
};
bool is_same (const mp_base* item) const template <typename T>
{ class mp_impl_const : public mp_base {
const mp_impl* i = reinterpret_cast<const mp_impl*>(item); public:
return (i != 0 && i->o == o && i->callback == callback); typedef void ((T::*mfp_pointer_type)()const);
} void call () const { (static_cast<const T*>(this->o)->*callback)(); }
private: mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {}
void (T::*callback)(PARAM1); const mfp_pointer_type callback;
T* o;
}; };
public: public:
typedef PARAM1 param1_type; typedef void param1_type;
typedef void param2_type; typedef void param2_type;
typedef void param3_type; typedef void param3_type;
typedef void param4_type; typedef void param4_type;
member_function_pointer_kernel_1 ( void operator() () const { static_cast<const mp_base*>((const void*)mp_memory.data)->call(); }
) :
mp(0)
{}
member_function_pointer_kernel_1( // This is here just to validate the assumption that our block of memory we have made
const member_function_pointer_kernel_1& item // in mp_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 :)
mp(0) member_function_pointer_kernel_1()
{ { COMPILE_TIME_ASSERT(sizeof(mp_memory.data) >= sizeof(mp_impl_T<mp_impl<dummy> >));
if (item.is_set()) COMPILE_TIME_ASSERT(sizeof(mp_memory.data) >= sizeof(mp_impl_T<mp_impl_const<dummy> >)); }
mp = item.mp->clone();
}
member_function_pointer_kernel_1& operator=( template <typename T> void set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
const member_function_pointer_kernel_1& item { mp_impl_T<mp_impl<T> >(&object,cb).clone(mp_memory.data); }
)
{
if (this != &item)
{
clear();
if (item.is_set()) template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
mp = item.mp->clone(); { mp_impl_T<mp_impl_const<T> >((void*)&object,cb).clone(mp_memory.data); }
}
return *this;
}
bool operator == ( };
const member_function_pointer_kernel_1& item
) const
{
if (is_set() != item.is_set())
return false;
if (is_set() == false)
return true;
return mp->is_same(item.mp);
}
bool operator != ( // ----------------------------------------------------------------------------------------
const member_function_pointer_kernel_1& item
) const { return !(*this == item); }
~member_function_pointer_kernel_1 ( template <
) typename PARAM1
{ >
if (mp) class member_function_pointer_kernel_1<PARAM1,void,void,void> : public mfp_kernel_1_base_class
delete mp; {
} class mp_base : public mp_base_base {
public:
mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {}
virtual void call(PARAM1) const = 0;
};
void clear( template <typename T>
) class mp_impl : public mp_base {
{ public:
if (mp) typedef void (T::*mfp_pointer_type)(PARAM1) ;
{ void call (PARAM1 p1) const { (static_cast<T*>(this->o)->*callback)(p1); }
delete mp;
mp = 0;
}
}
bool is_set ( mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {}
) const { return mp != 0; } const mfp_pointer_type callback;
};
template <
typename T
>
void set (
T& object,
void (T::*cb)(PARAM1)
)
{
clear();
mp = new mp_impl<T>(object,cb);
}
void operator () ( template <typename T>
PARAM1 param1 class mp_impl_const : public mp_base {
) const { mp->call(param1); } public:
typedef void ((T::*mfp_pointer_type)(PARAM1)const);
void call (PARAM1 p1) const { (static_cast<const T*>(this->o)->*callback)(p1); }
void swap ( mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {}
member_function_pointer_kernel_1& item const mfp_pointer_type callback;
) { exchange(mp,item.mp); } };
private: public:
typedef PARAM1 param1_type;
typedef void param2_type;
typedef void param3_type;
typedef void param4_type;
void operator() (PARAM1 p1) const { static_cast<const mp_base*>((const void*)mp_memory.data)->call(p1); }
mp_base* mp; // This is here just to validate the assumption that our block of memory we have made
// in mp_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 :)
member_function_pointer_kernel_1()
{ COMPILE_TIME_ASSERT(sizeof(mp_memory.data) >= sizeof(mp_impl_T<mp_impl<dummy> >));
COMPILE_TIME_ASSERT(sizeof(mp_memory.data) >= sizeof(mp_impl_T<mp_impl_const<dummy> >)); }
template <typename T> void set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
{ mp_impl_T<mp_impl<T> >(&object,cb).clone(mp_memory.data); }
template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
{ mp_impl_T<mp_impl_const<T> >((void*)&object,cb).clone(mp_memory.data); }
}; };
...@@ -345,57 +277,32 @@ namespace dlib ...@@ -345,57 +277,32 @@ namespace dlib
typename PARAM1, typename PARAM1,
typename PARAM2 typename PARAM2
> >
class member_function_pointer_kernel_1<PARAM1,PARAM2,void,void> class member_function_pointer_kernel_1<PARAM1,PARAM2,void,void> : public mfp_kernel_1_base_class
{ {
/*! class mp_base : public mp_base_base {
INITIAL VALUE
- mp == 0
CONVENTION
- is_set() == (mp != 0)
!*/
class mp_base
{
public: public:
virtual ~mp_base(){} mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {}
virtual void call(PARAM1,PARAM2) const = 0; virtual void call(PARAM1,PARAM2) const = 0;
virtual mp_base* clone() const = 0;
virtual bool is_same (const mp_base* item) const = 0;
}; };
template <typename T> template <typename T>
class mp_impl : public mp_base class mp_impl : public mp_base {
{
public: public:
mp_impl ( typedef void (T::*mfp_pointer_type)(PARAM1,PARAM2) ;
T& object, void call (PARAM1 p1, PARAM2 p2) const { (static_cast<T*>(this->o)->*callback)(p1,p2); }
void (T::*cb)(PARAM1,PARAM2)
) :
callback(cb),
o(&object)
{
}
void call ( mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {}
PARAM1 param1, const mfp_pointer_type callback;
PARAM2 param2 };
) const
{
(o->*callback)(param1,param2);
}
mp_base* clone() const { return new mp_impl(*o,callback); }
bool is_same (const mp_base* item) const template <typename T>
{ class mp_impl_const : public mp_base {
const mp_impl* i = reinterpret_cast<const mp_impl*>(item); public:
return (i != 0 && i->o == o && i->callback == callback); typedef void ((T::*mfp_pointer_type)(PARAM1,PARAM2)const);
} void call (PARAM1 p1, PARAM2 p2) const { (static_cast<const T*>(this->o)->*callback)(p1,p2); }
private: mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {}
void (T::*callback)(PARAM1,PARAM2); const mfp_pointer_type callback;
T* o;
}; };
public: public:
...@@ -404,93 +311,20 @@ namespace dlib ...@@ -404,93 +311,20 @@ namespace dlib
typedef void param3_type; typedef void param3_type;
typedef void param4_type; typedef void param4_type;
member_function_pointer_kernel_1 ( void operator() (PARAM1 p1, PARAM2 p2) const { static_cast<const mp_base*>((const void*)mp_memory.data)->call(p1,p2); }
) :
mp(0)
{}
member_function_pointer_kernel_1(
const member_function_pointer_kernel_1& item
) :
mp(0)
{
if (item.is_set())
mp = item.mp->clone();
}
member_function_pointer_kernel_1& operator=(
const member_function_pointer_kernel_1& item
)
{
if (this != &item)
{
clear();
if (item.is_set())
mp = item.mp->clone();
}
return *this;
}
bool operator == (
const member_function_pointer_kernel_1& item
) const
{
if (is_set() != item.is_set())
return false;
if (is_set() == false)
return true;
return mp->is_same(item.mp);
}
bool operator != (
const member_function_pointer_kernel_1& item
) const { return !(*this == item); }
~member_function_pointer_kernel_1 (
)
{
if (mp)
delete mp;
}
void clear(
)
{
if (mp)
{
delete mp;
mp = 0;
}
}
bool is_set (
) const { return mp != 0; }
template <
typename T
>
void set (
T& object,
void (T::*cb)(PARAM1,PARAM2)
)
{
clear();
mp = new mp_impl<T>(object,cb);
}
void operator () (
PARAM1 param1,
PARAM2 param2
) const { mp->call(param1,param2); }
void swap ( // This is here just to validate the assumption that our block of memory we have made
member_function_pointer_kernel_1& item // in mp_memory.data is the right size to store the data for this object. If you
) { exchange(mp,item.mp); } // get a compiler error on this line then email me :)
member_function_pointer_kernel_1()
{ COMPILE_TIME_ASSERT(sizeof(mp_memory.data) >= sizeof(mp_impl_T<mp_impl<dummy> >));
COMPILE_TIME_ASSERT(sizeof(mp_memory.data) >= sizeof(mp_impl_T<mp_impl_const<dummy> >)); }
private: template <typename T> void set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
{ mp_impl_T<mp_impl<T> >(&object,cb).clone(mp_memory.data); }
mp_base* mp; template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
{ mp_impl_T<mp_impl_const<T> >((void*)&object,cb).clone(mp_memory.data); }
}; };
...@@ -501,58 +335,32 @@ namespace dlib ...@@ -501,58 +335,32 @@ namespace dlib
typename PARAM2, typename PARAM2,
typename PARAM3 typename PARAM3
> >
class member_function_pointer_kernel_1<PARAM1,PARAM2,PARAM3,void> class member_function_pointer_kernel_1<PARAM1,PARAM2,PARAM3,void> : public mfp_kernel_1_base_class
{ {
/*! class mp_base : public mp_base_base {
INITIAL VALUE
- mp == 0
CONVENTION
- is_set() == (mp != 0)
!*/
class mp_base
{
public: public:
virtual ~mp_base(){} mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {}
virtual void call(PARAM1,PARAM2,PARAM3) const = 0; virtual void call(PARAM1,PARAM2,PARAM3) const = 0;
virtual mp_base* clone() const = 0;
virtual bool is_same (const mp_base* item) const = 0;
}; };
template <typename T> template <typename T>
class mp_impl : public mp_base class mp_impl : public mp_base {
{
public: public:
mp_impl ( typedef void (T::*mfp_pointer_type)(PARAM1,PARAM2,PARAM3) ;
T& object, void call (PARAM1 p1, PARAM2 p2, PARAM3 p3) const { (static_cast<T*>(this->o)->*callback)(p1,p2,p3); }
void (T::*cb)(PARAM1,PARAM2,PARAM3)
) :
callback(cb),
o(&object)
{
}
void call (
PARAM1 param1,
PARAM2 param2,
PARAM3 param3
) const
{
(o->*callback)(param1,param2,param3);
}
mp_base* clone() const { return new mp_impl(*o,callback); } mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {}
const mfp_pointer_type callback;
};
bool is_same (const mp_base* item) const template <typename T>
{ class mp_impl_const : public mp_base {
const mp_impl* i = reinterpret_cast<const mp_impl*>(item); public:
return (i != 0 && i->o == o && i->callback == callback); typedef void ((T::*mfp_pointer_type)(PARAM1,PARAM2,PARAM3)const);
} void call (PARAM1 p1, PARAM2 p2, PARAM3 p3) const { (static_cast<const T*>(this->o)->*callback)(p1,p2,p3); }
private: mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {}
void (T::*callback)(PARAM1,PARAM2,PARAM3); const mfp_pointer_type callback;
T* o;
}; };
public: public:
...@@ -561,94 +369,20 @@ namespace dlib ...@@ -561,94 +369,20 @@ namespace dlib
typedef PARAM3 param3_type; typedef PARAM3 param3_type;
typedef void param4_type; typedef void param4_type;
member_function_pointer_kernel_1 ( void operator() (PARAM1 p1, PARAM2 p2, PARAM3 p3) const { static_cast<const mp_base*>((const void*)mp_memory.data)->call(p1,p2,p3); }
) :
mp(0)
{}
member_function_pointer_kernel_1(
const member_function_pointer_kernel_1& item
) :
mp(0)
{
if (item.is_set())
mp = item.mp->clone();
}
member_function_pointer_kernel_1& operator=(
const member_function_pointer_kernel_1& item
)
{
if (this != &item)
{
clear();
if (item.is_set()) // This is here just to validate the assumption that our block of memory we have made
mp = item.mp->clone(); // in mp_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 :)
return *this; member_function_pointer_kernel_1()
} { COMPILE_TIME_ASSERT(sizeof(mp_memory.data) >= sizeof(mp_impl_T<mp_impl<dummy> >));
COMPILE_TIME_ASSERT(sizeof(mp_memory.data) >= sizeof(mp_impl_T<mp_impl_const<dummy> >)); }
bool operator == ( template <typename T> void set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
const member_function_pointer_kernel_1& item { mp_impl_T<mp_impl<T> >(&object,cb).clone(mp_memory.data); }
) const
{
if (is_set() != item.is_set())
return false;
if (is_set() == false)
return true;
return mp->is_same(item.mp);
}
bool operator != ( template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
const member_function_pointer_kernel_1& item { mp_impl_T<mp_impl_const<T> >((void*)&object,cb).clone(mp_memory.data); }
) const { return !(*this == item); }
~member_function_pointer_kernel_1 (
)
{
if (mp)
delete mp;
}
void clear(
)
{
if (mp)
{
delete mp;
mp = 0;
}
}
bool is_set (
) const { return mp != 0; }
template <
typename T
>
void set (
T& object,
void (T::*cb)(PARAM1,PARAM2,PARAM3)
)
{
clear();
mp = new mp_impl<T>(object,cb);
}
void operator () (
PARAM1 param1,
PARAM2 param2,
PARAM3 param3
) const { mp->call(param1,param2,param3); }
void swap (
member_function_pointer_kernel_1& item
) { exchange(mp,item.mp); }
private:
mp_base* mp;
}; };
...@@ -660,59 +394,32 @@ namespace dlib ...@@ -660,59 +394,32 @@ namespace dlib
typename PARAM3, typename PARAM3,
typename PARAM4 typename PARAM4
> >
class member_function_pointer_kernel_1 class member_function_pointer_kernel_1 : public mfp_kernel_1_base_class
{ {
/*! class mp_base : public mp_base_base {
INITIAL VALUE
- mp == 0
CONVENTION
- is_set() == (mp != 0)
!*/
class mp_base
{
public: public:
virtual ~mp_base(){} mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {}
virtual void call(PARAM1,PARAM2,PARAM3,PARAM4) const = 0; virtual void call(PARAM1,PARAM2,PARAM3,PARAM4) const = 0;
virtual mp_base* clone() const = 0;
virtual bool is_same (const mp_base* item) const = 0;
}; };
template <typename T> template <typename T>
class mp_impl : public mp_base class mp_impl : public mp_base {
{
public: public:
mp_impl ( typedef void (T::*mfp_pointer_type)(PARAM1,PARAM2,PARAM3, PARAM4) ;
T& object, void call (PARAM1 p1, PARAM2 p2, PARAM3 p3, PARAM4 p4) const { (static_cast<T*>(this->o)->*callback)(p1,p2,p3,p4); }
void (T::*cb)(PARAM1,PARAM2,PARAM3,PARAM4)
) :
callback(cb),
o(&object)
{
}
void call (
PARAM1 param1,
PARAM2 param2,
PARAM3 param3,
PARAM4 param4
) const
{
(o->*callback)(param1,param2,param3,param4);
}
mp_base* clone() const { return new mp_impl(*o,callback); } mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {}
const mfp_pointer_type callback;
};
bool is_same (const mp_base* item) const template <typename T>
{ class mp_impl_const : public mp_base {
const mp_impl* i = reinterpret_cast<const mp_impl*>(item); public:
return (i != 0 && i->o == o && i->callback == callback); typedef void ((T::*mfp_pointer_type)(PARAM1,PARAM2,PARAM3,PARAM4)const);
} void call (PARAM1 p1, PARAM2 p2, PARAM3 p3, PARAM4 p4) const { (static_cast<const T*>(this->o)->*callback)(p1,p2,p3,p4); }
private: mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {}
void (T::*callback)(PARAM1,PARAM2,PARAM3,PARAM4); const mfp_pointer_type callback;
T* o;
}; };
public: public:
...@@ -721,95 +428,21 @@ namespace dlib ...@@ -721,95 +428,21 @@ namespace dlib
typedef PARAM3 param3_type; typedef PARAM3 param3_type;
typedef PARAM4 param4_type; typedef PARAM4 param4_type;
member_function_pointer_kernel_1 ( void operator() (PARAM1 p1, PARAM2 p2, PARAM3 p3, PARAM4 p4) const
) : { static_cast<const mp_base*>((const void*)mp_memory.data)->call(p1,p2,p3,p4); }
mp(0)
{}
member_function_pointer_kernel_1( // This is here just to validate the assumption that our block of memory we have made
const member_function_pointer_kernel_1& item // in mp_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 :)
mp(0) member_function_pointer_kernel_1()
{ { COMPILE_TIME_ASSERT(sizeof(mp_memory.data) >= sizeof(mp_impl_T<mp_impl<dummy> >));
if (item.is_set()) COMPILE_TIME_ASSERT(sizeof(mp_memory.data) >= sizeof(mp_impl_T<mp_impl_const<dummy> >)); }
mp = item.mp->clone();
}
member_function_pointer_kernel_1& operator=(
const member_function_pointer_kernel_1& item
)
{
if (this != &item)
{
clear();
if (item.is_set())
mp = item.mp->clone();
}
return *this;
}
bool operator == (
const member_function_pointer_kernel_1& item
) const
{
if (is_set() != item.is_set())
return false;
if (is_set() == false)
return true;
return mp->is_same(item.mp);
}
bool operator != (
const member_function_pointer_kernel_1& item
) const { return !(*this == item); }
~member_function_pointer_kernel_1 (
)
{
if (mp)
delete mp;
}
void clear(
)
{
if (mp)
{
delete mp;
mp = 0;
}
}
bool is_set ( template <typename T> void set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
) const { return mp != 0; } { mp_impl_T<mp_impl<T> >(&object,cb).clone(mp_memory.data); }
template <
typename T
>
void set (
T& object,
void (T::*cb)(PARAM1,PARAM2,PARAM3,PARAM4)
)
{
clear();
mp = new mp_impl<T>(object,cb);
}
void operator () (
PARAM1 param1,
PARAM2 param2,
PARAM3 param3,
PARAM4 param4
) const { mp->call(param1,param2,param3,param4); }
void swap (
member_function_pointer_kernel_1& item
) { exchange(mp,item.mp); }
private:
mp_base* mp; template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
{ mp_impl_T<mp_impl_const<T> >((void*)&object,cb).clone(mp_memory.data); }
}; };
......
...@@ -16,17 +16,6 @@ namespace dlib ...@@ -16,17 +16,6 @@ namespace dlib
> >
class member_function_pointer; class member_function_pointer;
template <
typename PARAM1,
typename PARAM2,
typename PARAM3,
typename PARAM4
>
void swap (
member_function_pointer<PARAM1,PARAM2,PARAM3,PARAM4>& a,
member_function_pointer<PARAM1,PARAM2,PARAM3,PARAM4>& b
) { a.swap(b); }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <> template <>
...@@ -53,9 +42,9 @@ namespace dlib ...@@ -53,9 +42,9 @@ namespace dlib
member_function_pointer<> my_pointer; member_function_pointer<> my_pointer;
To use a pointer to a function that takes a single int you would say: To use a pointer to a function that takes a single int you would say:
member_function_pointer<int> my_pointer; member_function_pointer<int> my_pointer;
To use a pointer to a function that takes an int and then a string To use a pointer to a function that takes an int and then a reference
you would say: to a string you would say:
member_function_pointer<int,string> my_pointer; member_function_pointer<int,string&> my_pointer;
Also note that the formal comments are only present for the first Also note that the formal comments are only present for the first
template specialization. They are all exactly the same except for the template specialization. They are all exactly the same except for the
...@@ -160,6 +149,38 @@ namespace dlib ...@@ -160,6 +149,38 @@ namespace dlib
If this exception is thrown then #is_set() == false If this exception is thrown then #is_set() == false
!*/ !*/
template <
typename T
>
void set (
const T& object,
void (T::*cb)()const
);
/*!
requires
- cb == a valid member function pointer for class T
ensures
- #is_set() == true
- calls to this->operator() will call (object.*cb)()
throws
- std::bad_alloc
If this exception is thrown then #is_set() == false
!*/
operator bool (
) const;
/*!
ensures
- returns is_set()
!*/
bool operator! (
) const;
/*!
ensures
- returns !is_set()
!*/
void operator () ( void operator () (
) const; ) const;
/*! /*!
...@@ -229,6 +250,18 @@ namespace dlib ...@@ -229,6 +250,18 @@ namespace dlib
void (T::*cb)(PARAM1) void (T::*cb)(PARAM1)
); );
template <typename T>
void set (
const T& object,
void (T::*cb)(PARAM1)const
);
operator bool (
) const;
bool operator! (
) const;
void operator () ( void operator () (
PARAM1 param1 PARAM1 param1
) const; ) const;
...@@ -284,6 +317,18 @@ namespace dlib ...@@ -284,6 +317,18 @@ namespace dlib
void (T::*cb)(PARAM1,PARAM2) void (T::*cb)(PARAM1,PARAM2)
); );
template <typename T>
void set (
const T& object,
void (T::*cb)(PARAM1,PARAM2)const
);
operator bool (
) const;
bool operator! (
) const;
void operator () ( void operator () (
PARAM1 param1, PARAM1 param1,
PARAM2 param2 PARAM2 param2
...@@ -341,6 +386,18 @@ namespace dlib ...@@ -341,6 +386,18 @@ namespace dlib
void (T::*cb)(PARAM1,PARAM2,PARAM3) void (T::*cb)(PARAM1,PARAM2,PARAM3)
); );
template <typename T>
void set (
const T& object,
void (T::*cb)(PARAM1,PARAM2,PARAM3)const
);
operator bool (
) const;
bool operator! (
) const;
void operator () ( void operator () (
PARAM1 param1, PARAM1 param1,
PARAM2 param2, PARAM2 param2,
...@@ -400,6 +457,18 @@ namespace dlib ...@@ -400,6 +457,18 @@ namespace dlib
void (T::*cb)(PARAM1,PARAM2,PARAM3,PARAM4) void (T::*cb)(PARAM1,PARAM2,PARAM3,PARAM4)
); );
template <typename T>
void set (
const T& object,
void (T::*cb)(PARAM1,PARAM2,PARAM3,PARAM4)const
);
operator bool (
) const;
bool operator! (
) const;
void operator () ( void operator () (
PARAM1 param1, PARAM1 param1,
PARAM2 param2, PARAM2 param2,
......
...@@ -19,18 +19,6 @@ namespace dlib ...@@ -19,18 +19,6 @@ namespace dlib
> >
class member_function_pointer_kernel_c; class member_function_pointer_kernel_c;
template <
typename mfpb,
typename PARAM1,
typename PARAM2,
typename PARAM3,
typename PARAM4
>
void swap (
member_function_pointer_kernel_c<mfpb,PARAM1,PARAM2,PARAM3,PARAM4>& a,
member_function_pointer_kernel_c<mfpb,PARAM1,PARAM2,PARAM3,PARAM4>& b
) { a.swap(b); }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < template <
...@@ -60,6 +48,25 @@ namespace dlib ...@@ -60,6 +48,25 @@ namespace dlib
mfpb::set(object,cb); mfpb::set(object,cb);
} }
template <
typename T
>
void set (
const T& object,
void (T::*cb)()const
)
{
// make sure requires clause is not broken
DLIB_CASSERT(cb != 0,
"\tvoid member_function_pointer::set"
<< "\n\tthe member function pointer can't be null"
<< "\n\tthis: " << this
);
// call the real function
mfpb::set(object,cb);
}
void operator () ( void operator () (
) const ) const
{ {
...@@ -105,6 +112,25 @@ namespace dlib ...@@ -105,6 +112,25 @@ namespace dlib
mfpb::set(object,cb); mfpb::set(object,cb);
} }
template <
typename T
>
void set (
const T& object,
void (T::*cb)(PARAM1)const
)
{
// make sure requires clause is not broken
DLIB_CASSERT(cb != 0,
"\tvoid member_function_pointer::set"
<< "\n\tthe member function pointer can't be null"
<< "\n\tthis: " << this
);
// call the real function
mfpb::set(object,cb);
}
void operator () ( void operator () (
PARAM1 param1 PARAM1 param1
) const ) const
...@@ -152,6 +178,25 @@ namespace dlib ...@@ -152,6 +178,25 @@ namespace dlib
mfpb::set(object,cb); mfpb::set(object,cb);
} }
template <
typename T
>
void set (
const T& object,
void (T::*cb)(PARAM1,PARAM2)const
)
{
// make sure requires clause is not broken
DLIB_CASSERT(cb != 0,
"\tvoid member_function_pointer::set"
<< "\n\tthe member function pointer can't be null"
<< "\n\tthis: " << this
);
// call the real function
mfpb::set(object,cb);
}
void operator () ( void operator () (
PARAM1 param1, PARAM1 param1,
PARAM2 param2 PARAM2 param2
...@@ -201,6 +246,25 @@ namespace dlib ...@@ -201,6 +246,25 @@ namespace dlib
mfpb::set(object,cb); mfpb::set(object,cb);
} }
template <
typename T
>
void set (
const T& object,
void (T::*cb)(PARAM1,PARAM2,PARAM3)const
)
{
// make sure requires clause is not broken
DLIB_CASSERT(cb != 0,
"\tvoid member_function_pointer::set"
<< "\n\tthe member function pointer can't be null"
<< "\n\tthis: " << this
);
// call the real function
mfpb::set(object,cb);
}
void operator () ( void operator () (
PARAM1 param1, PARAM1 param1,
PARAM2 param2, PARAM2 param2,
...@@ -252,6 +316,25 @@ namespace dlib ...@@ -252,6 +316,25 @@ namespace dlib
mfpb::set(object,cb); mfpb::set(object,cb);
} }
template <
typename T
>
void set (
const T& object,
void (T::*cb)(PARAM1,PARAM2,PARAM3,PARAM4)const
)
{
// make sure requires clause is not broken
DLIB_CASSERT(cb != 0,
"\tvoid member_function_pointer::set"
<< "\n\tthe member function pointer can't be null"
<< "\n\tthis: " << this
);
// call the real function
mfpb::set(object,cb);
}
void operator () ( void operator () (
PARAM1 param1, PARAM1 param1,
PARAM2 param2, PARAM2 param2,
......
...@@ -19,6 +19,34 @@ namespace ...@@ -19,6 +19,34 @@ namespace
logger dlog("test.member_function_pointer"); logger dlog("test.member_function_pointer");
class mfp_test_helper_other
{
public:
mfp_test_helper_other (
): i(-1) {}
mutable int i;
void go0 (
) { i = 0; }
void go1 (
int v1
) { i = 1*v1; }
void go2 (
int v1,int v2
) { i = 2*v1*v2; }
void go3 (
int v1,int v2,int v3
) { i = 3*v1*v2*v3; }
void go4 (
int v1,int v2,int v3,int v4
) { i = 4*v1*v2*v3*v4; }
};
class mfp_test_helper class mfp_test_helper
{ {
public: public:
...@@ -26,27 +54,54 @@ namespace ...@@ -26,27 +54,54 @@ namespace
): i(-1) {} ): i(-1) {}
int i; mutable int i;
void go0 ( void go0 (
) { i = 0; } ) { i = 0; }
void go1 ( void go1 (
int int v1
) { i = 1; } ) { i = 1*v1; }
void go2 ( void go2 (
int,int int v1,int v2
) { i = 2; } ) { i = 2*v1*v2; }
void go3 ( void go3 (
int,int,int int v1,int v2,int v3
) { i = 3; } ) { i = 3*v1*v2*v3; }
void go4 ( void go4 (
int,int,int,int int v1,int v2,int v3,int v4
) { i = 4; } ) { i = 4*v1*v2*v3*v4; }
};
class mfp_test_helper_const
{
public:
mfp_test_helper_const (
): i(-1) {}
mutable int i;
void go0 (
) const { i = 0; }
void go1 (
int v1
) const { i = 1*v1; }
void go2 (
int v1,int v2
) const { i = 2*v1*v2; }
void go3 (
int v1,int v2,int v3
) const { i = 3*v1*v2*v3; }
void go4 (
int v1,int v2,int v3,int v4
) const { i = 4*v1*v2*v3*v4; }
}; };
template < template <
template <typename P1 = void, typename P2 = void, typename P3 = void, typename P4 = void> class mfp template <typename P1 = void, typename P2 = void, typename P3 = void, typename P4 = void> class mfp,
typename test_helper
> >
void member_function_pointer_kernel_test ( void member_function_pointer_kernel_test (
) )
...@@ -59,7 +114,7 @@ namespace ...@@ -59,7 +114,7 @@ namespace
{ {
mfp_test_helper helper; test_helper helper;
mfp<> a0, b0; mfp<> a0, b0;
mfp<int> a1, b1; mfp<int> a1, b1;
...@@ -89,33 +144,64 @@ namespace ...@@ -89,33 +144,64 @@ namespace
DLIB_CASSERT(a0c.is_set() == false,""); DLIB_CASSERT(a0c.is_set() == false,"");
DLIB_CASSERT(b0c.is_set() == false,""); DLIB_CASSERT(b0c.is_set() == false,"");
DLIB_CASSERT(!a0 ,"");
DLIB_CASSERT(!b0 ,"");
DLIB_CASSERT(!a0c,"");
DLIB_CASSERT(!b0c,"");
DLIB_CASSERT(a1.is_set() == false,""); DLIB_CASSERT(a1.is_set() == false,"");
DLIB_CASSERT(b1.is_set() == false,""); DLIB_CASSERT(b1.is_set() == false,"");
DLIB_CASSERT(a1c.is_set() == false,""); DLIB_CASSERT(a1c.is_set() == false,"");
DLIB_CASSERT(b1c.is_set() == false,""); DLIB_CASSERT(b1c.is_set() == false,"");
DLIB_CASSERT(!a1 ,"");
DLIB_CASSERT(!b1 ,"");
DLIB_CASSERT(!a1c,"");
DLIB_CASSERT(!b1c,"");
DLIB_CASSERT(a2.is_set() == false,""); DLIB_CASSERT(a2.is_set() == false,"");
DLIB_CASSERT(b2.is_set() == false,""); DLIB_CASSERT(b2.is_set() == false,"");
DLIB_CASSERT(a2c.is_set() == false,""); DLIB_CASSERT(a2c.is_set() == false,"");
DLIB_CASSERT(b2c.is_set() == false,""); DLIB_CASSERT(b2c.is_set() == false,"");
DLIB_CASSERT(!a2,"");
DLIB_CASSERT(!b2,"");
DLIB_CASSERT(!a2c,"");
DLIB_CASSERT(!b2c,"");
DLIB_CASSERT(a3.is_set() == false,""); DLIB_CASSERT(a3.is_set() == false,"");
DLIB_CASSERT(b3.is_set() == false,""); DLIB_CASSERT(b3.is_set() == false,"");
DLIB_CASSERT(a3c.is_set() == false,""); DLIB_CASSERT(a3c.is_set() == false,"");
DLIB_CASSERT(b3c.is_set() == false,""); DLIB_CASSERT(b3c.is_set() == false,"");
DLIB_CASSERT(!a3,"");
DLIB_CASSERT(!b3,"");
DLIB_CASSERT(!a3c,"");
DLIB_CASSERT(!b3c,"");
DLIB_CASSERT(a4.is_set() == false,""); DLIB_CASSERT(a4.is_set() == false,"");
DLIB_CASSERT(b4.is_set() == false,""); DLIB_CASSERT(b4.is_set() == false,"");
DLIB_CASSERT(a4c.is_set() == false,""); DLIB_CASSERT(a4c.is_set() == false,"");
DLIB_CASSERT(b4c.is_set() == false,""); DLIB_CASSERT(b4c.is_set() == false,"");
a0.set(helper,&mfp_test_helper::go0); DLIB_CASSERT(!a4,"");
a0c.set(helper,&mfp_test_helper::go0); DLIB_CASSERT(!b4,"");
DLIB_CASSERT(!a4c,"");
DLIB_CASSERT(!b4c,"");
a0.set(helper,&test_helper::go0);
a0c.set(helper,&test_helper::go0);
DLIB_CASSERT(a0.is_set() == true,""); DLIB_CASSERT(a0.is_set() == true,"");
DLIB_CASSERT(a0c.is_set() == true,""); DLIB_CASSERT(a0c.is_set() == true,"");
DLIB_CASSERT(b0.is_set() == false,""); DLIB_CASSERT(b0.is_set() == false,"");
DLIB_CASSERT(b0c.is_set() == false,""); DLIB_CASSERT(b0c.is_set() == false,"");
DLIB_CASSERT(a0,"");
DLIB_CASSERT(a0c,"");
DLIB_CASSERT(!b0,"");
DLIB_CASSERT(!b0c,"");
a0 = a0; a0 = a0;
DLIB_CASSERT(a0 == a0, ""); DLIB_CASSERT(a0 == a0, "");
DLIB_CASSERT(!(a0 != a0),""); DLIB_CASSERT(!(a0 != a0),"");
...@@ -124,6 +210,11 @@ namespace ...@@ -124,6 +210,11 @@ namespace
DLIB_CASSERT(b0.is_set() == false,""); DLIB_CASSERT(b0.is_set() == false,"");
DLIB_CASSERT(b0c.is_set() == false,""); DLIB_CASSERT(b0c.is_set() == false,"");
DLIB_CASSERT(a0,"");
DLIB_CASSERT(a0c,"");
DLIB_CASSERT(!b0,"");
DLIB_CASSERT(!b0c,"");
swap(a0,b0); swap(a0,b0);
swap(a0c,b0c); swap(a0c,b0c);
DLIB_CASSERT(a0.is_set() == false,""); DLIB_CASSERT(a0.is_set() == false,"");
...@@ -131,6 +222,11 @@ namespace ...@@ -131,6 +222,11 @@ namespace
DLIB_CASSERT(b0.is_set() == true,""); DLIB_CASSERT(b0.is_set() == true,"");
DLIB_CASSERT(b0c.is_set() == true,""); DLIB_CASSERT(b0c.is_set() == true,"");
DLIB_CASSERT(!a0,"");
DLIB_CASSERT(!a0c,"");
DLIB_CASSERT(b0,"");
DLIB_CASSERT(b0c,"");
a0 = b0; a0 = b0;
DLIB_CASSERT(a0 == a0, ""); DLIB_CASSERT(a0 == a0, "");
DLIB_CASSERT(a0 == b0, ""); DLIB_CASSERT(a0 == b0, "");
...@@ -140,6 +236,11 @@ namespace ...@@ -140,6 +236,11 @@ namespace
DLIB_CASSERT(b0.is_set() == true,""); DLIB_CASSERT(b0.is_set() == true,"");
DLIB_CASSERT(b0c.is_set() == true,""); DLIB_CASSERT(b0c.is_set() == true,"");
DLIB_CASSERT(a0 ,"");
DLIB_CASSERT(!a0c,"");
DLIB_CASSERT(b0,"");
DLIB_CASSERT(b0c,"");
a0.clear(); a0.clear();
a0c.clear(); a0c.clear();
...@@ -151,8 +252,8 @@ namespace ...@@ -151,8 +252,8 @@ namespace
DLIB_CASSERT(b0c.is_set() == false,""); DLIB_CASSERT(b0c.is_set() == false,"");
a1.set(helper,&mfp_test_helper::go1); a1.set(helper,&test_helper::go1);
a1c.set(helper,&mfp_test_helper::go1); a1c.set(helper,&test_helper::go1);
DLIB_CASSERT(a1.is_set() == true,""); DLIB_CASSERT(a1.is_set() == true,"");
DLIB_CASSERT(a1c.is_set() == true,""); DLIB_CASSERT(a1c.is_set() == true,"");
DLIB_CASSERT(b1.is_set() == false,""); DLIB_CASSERT(b1.is_set() == false,"");
...@@ -164,6 +265,11 @@ namespace ...@@ -164,6 +265,11 @@ namespace
DLIB_CASSERT(b1.is_set() == true,""); DLIB_CASSERT(b1.is_set() == true,"");
DLIB_CASSERT(b1c.is_set() == true,""); DLIB_CASSERT(b1c.is_set() == true,"");
DLIB_CASSERT(!a1,"");
DLIB_CASSERT(!a1c,"");
DLIB_CASSERT(b1,"");
DLIB_CASSERT(b1c,"");
a1 = b1; a1 = b1;
DLIB_CASSERT(a1 == a1, ""); DLIB_CASSERT(a1 == a1, "");
...@@ -185,8 +291,8 @@ namespace ...@@ -185,8 +291,8 @@ namespace
DLIB_CASSERT(b1c.is_set() == false,""); DLIB_CASSERT(b1c.is_set() == false,"");
a2.set(helper,&mfp_test_helper::go2); a2.set(helper,&test_helper::go2);
a2c.set(helper,&mfp_test_helper::go2); a2c.set(helper,&test_helper::go2);
DLIB_CASSERT(a2.is_set() == true,""); DLIB_CASSERT(a2.is_set() == true,"");
DLIB_CASSERT(a2c.is_set() == true,""); DLIB_CASSERT(a2c.is_set() == true,"");
DLIB_CASSERT(b2.is_set() == false,""); DLIB_CASSERT(b2.is_set() == false,"");
...@@ -198,6 +304,27 @@ namespace ...@@ -198,6 +304,27 @@ namespace
DLIB_CASSERT(b2.is_set() == true,""); DLIB_CASSERT(b2.is_set() == true,"");
DLIB_CASSERT(b2c.is_set() == true,""); DLIB_CASSERT(b2c.is_set() == true,"");
DLIB_CASSERT(!a2,"");
DLIB_CASSERT(!a2c,"");
DLIB_CASSERT(b2,"");
DLIB_CASSERT(b2c,"");
if (b2)
{
}
else
{
DLIB_CASSERT(false,"");
}
if (a2c)
{
DLIB_CASSERT(false,"");
}
else
{
DLIB_CASSERT(true,"");
}
a2 = b2; a2 = b2;
DLIB_CASSERT(a2 == a2, ""); DLIB_CASSERT(a2 == a2, "");
DLIB_CASSERT(a2 == b2, ""); DLIB_CASSERT(a2 == b2, "");
...@@ -217,8 +344,8 @@ namespace ...@@ -217,8 +344,8 @@ namespace
DLIB_CASSERT(b2c.is_set() == false,""); DLIB_CASSERT(b2c.is_set() == false,"");
a3.set(helper,&mfp_test_helper::go3); a3.set(helper,&test_helper::go3);
a3c.set(helper,&mfp_test_helper::go3); a3c.set(helper,&test_helper::go3);
DLIB_CASSERT(a3.is_set() == true,""); DLIB_CASSERT(a3.is_set() == true,"");
DLIB_CASSERT(a3c.is_set() == true,""); DLIB_CASSERT(a3c.is_set() == true,"");
DLIB_CASSERT(b3.is_set() == false,""); DLIB_CASSERT(b3.is_set() == false,"");
...@@ -250,8 +377,8 @@ namespace ...@@ -250,8 +377,8 @@ namespace
DLIB_CASSERT(b3c.is_set() == false,""); DLIB_CASSERT(b3c.is_set() == false,"");
a4.set(helper,&mfp_test_helper::go4); a4.set(helper,&test_helper::go4);
a4c.set(helper,&mfp_test_helper::go4); a4c.set(helper,&test_helper::go4);
DLIB_CASSERT(a4.is_set() == true,""); DLIB_CASSERT(a4.is_set() == true,"");
DLIB_CASSERT(a4c.is_set() == true,""); DLIB_CASSERT(a4c.is_set() == true,"");
DLIB_CASSERT(b4.is_set() == false,""); DLIB_CASSERT(b4.is_set() == false,"");
...@@ -286,8 +413,8 @@ namespace ...@@ -286,8 +413,8 @@ namespace
DLIB_CASSERT(b4c.is_set() == false,""); DLIB_CASSERT(b4c.is_set() == false,"");
a0.set(helper,&mfp_test_helper::go0); a0.set(helper,&test_helper::go0);
a0c.set(helper,&mfp_test_helper::go0); a0c.set(helper,&test_helper::go0);
b0 = a0; b0 = a0;
b0c = a0c; b0c = a0c;
helper.i = -1; helper.i = -1;
...@@ -304,76 +431,99 @@ namespace ...@@ -304,76 +431,99 @@ namespace
DLIB_CASSERT(helper.i == 0,""); DLIB_CASSERT(helper.i == 0,"");
a1.set(helper,&mfp_test_helper::go1); a1.set(helper,&test_helper::go1);
a1c.set(helper,&mfp_test_helper::go1); a1c.set(helper,&test_helper::go1);
b1 = a1; b1 = a1;
b1c = a1c; b1c = a1c;
helper.i = -1; helper.i = -1;
a1(0); a1(1);
DLIB_CASSERT(helper.i == 1,""); DLIB_CASSERT(helper.i == 1,"");
helper.i = -1; helper.i = -1;
b1(0); b1(10);
DLIB_CASSERT(helper.i == 1,""); DLIB_CASSERT(helper.i == 1*10,"");
helper.i = -1; helper.i = -1;
a1c(0); a1c(20);
DLIB_CASSERT(helper.i == 1,""); DLIB_CASSERT(helper.i == 1*20,"");
helper.i = -1; helper.i = -1;
b1c(0); b1c(30);
DLIB_CASSERT(helper.i == 1,""); DLIB_CASSERT(helper.i == 1*30,"");
a2.set(helper,&mfp_test_helper::go2); a2.set(helper,&test_helper::go2);
a2c.set(helper,&mfp_test_helper::go2); a2c.set(helper,&test_helper::go2);
b2 = a2; b2 = a2;
b2c = a2c; b2c = a2c;
helper.i = -1; helper.i = -1;
a2(0,0); a2(1,2);
DLIB_CASSERT(helper.i == 2,""); DLIB_CASSERT(helper.i == 2*1*2,"");
helper.i = -1; helper.i = -1;
b2(0,0); b2(3,4);
DLIB_CASSERT(helper.i == 2,""); DLIB_CASSERT(helper.i == 2*3*4,"");
helper.i = -1; helper.i = -1;
a2c(0,0); a2c(5,6);
DLIB_CASSERT(helper.i == 2,""); DLIB_CASSERT(helper.i == 2*5*6,"");
helper.i = -1; helper.i = -1;
b2c(0,0); b2c(7,8);
DLIB_CASSERT(helper.i == 2,""); DLIB_CASSERT(helper.i == 2*7*8,"");
a3.set(helper,&mfp_test_helper::go3); a3.set(helper,&test_helper::go3);
a3c.set(helper,&mfp_test_helper::go3); a3c.set(helper,&test_helper::go3);
b3 = a3; b3 = a3;
b3c = a3c; b3c = a3c;
helper.i = -1; helper.i = -1;
a3(0,0,0); a3(1,2,3);
DLIB_CASSERT(helper.i == 3,""); DLIB_CASSERT(helper.i == 3*1*2*3,"");
helper.i = -1; helper.i = -1;
b3(0,0,0); b3(4,5,6);
DLIB_CASSERT(helper.i == 3,""); DLIB_CASSERT(helper.i == 3*4*5*6,"");
helper.i = -1; helper.i = -1;
a3c(0,0,0); a3c(7,8,9);
DLIB_CASSERT(helper.i == 3,""); DLIB_CASSERT(helper.i == 3*7*8*9,"");
helper.i = -1; helper.i = -1;
b3c(0,0,0); b3c(1,2,3);
DLIB_CASSERT(helper.i == 3,""); DLIB_CASSERT(helper.i == 3*1*2*3,"");
a4.set(helper,&mfp_test_helper::go4); a4.set(helper,&test_helper::go4);
a4c.set(helper,&mfp_test_helper::go4); a4c.set(helper,&test_helper::go4);
DLIB_CASSERT(a4 == a4c,"");
b4 = a4; b4 = a4;
b4c = a4c; b4c = a4c;
helper.i = -1; helper.i = -1;
a4(0,0,0,0); a4(1,2,3,4);
DLIB_CASSERT(helper.i == 4,""); DLIB_CASSERT(helper.i == 4*1*2*3*4,"");
helper.i = -1; helper.i = -1;
b4(0,0,0,0); b4(5,6,7,8);
DLIB_CASSERT(helper.i == 4,""); DLIB_CASSERT(helper.i == 4*5*6*7*8,"");
helper.i = -1; helper.i = -1;
a4c(0,0,0,0); a4c(9,1,2,3);
DLIB_CASSERT(helper.i == 4,""); DLIB_CASSERT(helper.i == 4*9*1*2*3,"");
helper.i = -1; helper.i = -1;
b4c(0,0,0,0); b4c(4,5,6,7);
DLIB_CASSERT(helper.i == 4,""); DLIB_CASSERT(helper.i == 4*4*5*6*7,"");
DLIB_CASSERT(a4 == b4,"");
DLIB_CASSERT(a4,"");
DLIB_CASSERT(a4 == b4,"");
a4.clear();
DLIB_CASSERT(a4 != b4,"");
DLIB_CASSERT(!a4,"");
DLIB_CASSERT(a4 == 0,"");
DLIB_CASSERT(a4 == a4,"");
a4 = a4;
DLIB_CASSERT(a4 != b4,"");
DLIB_CASSERT(!a4,"");
DLIB_CASSERT(a4 == a4,"");
mfp_test_helper_other other;
a4.set(other,&mfp_test_helper_other::go4);
DLIB_CASSERT(a4 != b4,"");
DLIB_CASSERT(a4,"");
DLIB_CASSERT(a4 == a4,"");
a4.set(helper,&test_helper::go4);
DLIB_CASSERT(a4 == b4,"");
DLIB_CASSERT(a4,"");
DLIB_CASSERT(a4 == a4,"");
...@@ -393,7 +543,8 @@ namespace ...@@ -393,7 +543,8 @@ namespace
void perform_test ( void perform_test (
) )
{ {
member_function_pointer_kernel_test<member_function_pointer_kernel_1>(); member_function_pointer_kernel_test<member_function_pointer_kernel_1,mfp_test_helper>();
member_function_pointer_kernel_test<member_function_pointer_kernel_1,mfp_test_helper_const>();
} }
} a; } a;
......
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