Commit d7ecc1fa authored by Davis King's avatar Davis King

Made the member_function_pointer more robust to the amount of memory in its stack

based block of memory not being big enough.  We should now be guaranteed that it
will either fit or it won't compile.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402630
parent 5faacf97
......@@ -25,9 +25,9 @@ namespace dlib
//----------- kernels ---------------
// kernel_1a
typedef member_function_pointer_kernel_1<PARAM1,PARAM2,PARAM3,PARAM4>
typedef mfpk1<PARAM1,PARAM2,PARAM3,PARAM4>
kernel_1a;
typedef member_function_pointer_kernel_c<kernel_1a>
typedef mfpkc<kernel_1a>
kernel_1a_c;
......
......@@ -19,7 +19,7 @@ namespace dlib
typename PARAM3 = void,
typename PARAM4 = void
>
class member_function_pointer_kernel_1;
class mfpk1;
// ----------------------------------------------------------------------------------------
......@@ -76,6 +76,17 @@ namespace dlib
mp_impl_T() : mp_impl(0,0) {}
mp_impl_T(void* ptr, mfp_pointer_type cb) : mp_impl(ptr,cb) {}
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 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 :)
COMPILE_TIME_ASSERT(sizeof(*this) <= mem_size);
clone(buf);
}
void clone (void* ptr) const { new(ptr) mp_impl_T(this->o,this->callback); }
bool is_same (const mp_base_base* item) const
{
......@@ -92,7 +103,8 @@ namespace dlib
}
};
struct dummy { void nonnull() {}; };
struct dummy_base { virtual void nonnull() {}; int a; };
struct dummy : virtual public dummy_base{ void nonnull() {}; };
typedef mp_impl_T<mp_null<dummy> > mp_null_impl;
public:
......@@ -102,7 +114,7 @@ namespace dlib
) { item.mp()->clone(mp_memory.data); }
mfp_kernel_1_base_class (
) { mp_null_impl().clone(mp_memory.data); }
) { mp_null_impl().safe_clone(mp_memory.data); }
bool operator == (
const mfp_kernel_1_base_class& item
......@@ -184,7 +196,7 @@ namespace dlib
// ----------------------------------------------------------------------------------------
template <>
class member_function_pointer_kernel_1<void,void,void,void> : public mfp_kernel_1_base_class<0>
class mfpk1<void,void,void,void> : public mfp_kernel_1_base_class<0>
{
class mp_base : public mp_base_base {
public:
......@@ -220,21 +232,14 @@ namespace dlib
void operator() () const { static_cast<const mp_base*>((const void*)mp_memory.data)->call(); }
// 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> >)); }
// the reason for putting disable_if on this function is that it avoids an overload
// resolution bug in visual studio.
template <typename T> typename disable_if<is_const_type<T>,void>::type
set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
{ destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).clone(mp_memory.data); }
{ destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).safe_clone(mp_memory.data); }
template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
{ destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).clone(mp_memory.data); }
{ destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).safe_clone(mp_memory.data); }
};
......@@ -243,7 +248,7 @@ namespace dlib
template <
typename PARAM1
>
class member_function_pointer_kernel_1<PARAM1,void,void,void> : public mfp_kernel_1_base_class<1>
class mfpk1<PARAM1,void,void,void> : public mfp_kernel_1_base_class<1>
{
class mp_base : public mp_base_base {
public:
......@@ -279,21 +284,14 @@ namespace dlib
void operator() (PARAM1 p1) const { static_cast<const mp_base*>((const void*)mp_memory.data)->call(p1); }
// 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> >)); }
// the reason for putting disable_if on this function is that it avoids an overload
// resolution bug in visual studio.
template <typename T> typename disable_if<is_const_type<T>,void>::type
set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
{ destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).clone(mp_memory.data); }
{ destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).safe_clone(mp_memory.data); }
template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
{ destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).clone(mp_memory.data); }
{ destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).safe_clone(mp_memory.data); }
};
......@@ -303,7 +301,7 @@ namespace dlib
typename PARAM1,
typename PARAM2
>
class member_function_pointer_kernel_1<PARAM1,PARAM2,void,void> : public mfp_kernel_1_base_class<2>
class mfpk1<PARAM1,PARAM2,void,void> : public mfp_kernel_1_base_class<2>
{
class mp_base : public mp_base_base {
public:
......@@ -339,21 +337,14 @@ namespace dlib
void operator() (PARAM1 p1, PARAM2 p2) const { static_cast<const mp_base*>((const void*)mp_memory.data)->call(p1,p2); }
// 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> >)); }
// the reason for putting disable_if on this function is that it avoids an overload
// resolution bug in visual studio.
template <typename T> typename disable_if<is_const_type<T>,void>::type
set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
{ destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).clone(mp_memory.data); }
{ destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).safe_clone(mp_memory.data); }
template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
{ destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).clone(mp_memory.data); }
{ destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).safe_clone(mp_memory.data); }
};
......@@ -364,7 +355,7 @@ namespace dlib
typename PARAM2,
typename PARAM3
>
class member_function_pointer_kernel_1<PARAM1,PARAM2,PARAM3,void> : public mfp_kernel_1_base_class<3>
class mfpk1<PARAM1,PARAM2,PARAM3,void> : public mfp_kernel_1_base_class<3>
{
class mp_base : public mp_base_base {
public:
......@@ -400,21 +391,14 @@ namespace dlib
void operator() (PARAM1 p1, PARAM2 p2, PARAM3 p3) const { static_cast<const mp_base*>((const void*)mp_memory.data)->call(p1,p2,p3); }
// 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> >)); }
// the reason for putting disable_if on this function is that it avoids an overload
// resolution bug in visual studio.
template <typename T> typename disable_if<is_const_type<T>,void>::type
set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
{ destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).clone(mp_memory.data); }
{ destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).safe_clone(mp_memory.data); }
template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
{ destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).clone(mp_memory.data); }
{ destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).safe_clone(mp_memory.data); }
};
......@@ -426,7 +410,7 @@ namespace dlib
typename PARAM3,
typename PARAM4
>
class member_function_pointer_kernel_1 : public mfp_kernel_1_base_class<4>
class mfpk1 : public mfp_kernel_1_base_class<4>
{
class mp_base : public mp_base_base {
public:
......@@ -463,21 +447,14 @@ namespace dlib
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); }
// 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> >)); }
// the reason for putting disable_if on this function is that it avoids an overload
// resolution bug in visual studio.
template <typename T> typename disable_if<is_const_type<T>,void>::type
set(T& object, typename mp_impl<T>::mfp_pointer_type cb)
{ destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).clone(mp_memory.data); }
{ destroy_mp_memory(); mp_impl_T<mp_impl<T> >(&object,cb).safe_clone(mp_memory.data); }
template <typename T> void set(const T& object, typename mp_impl_const<T>::mfp_pointer_type cb)
{ destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).clone(mp_memory.data); }
{ destroy_mp_memory(); mp_impl_T<mp_impl_const<T> >((void*)&object,cb).safe_clone(mp_memory.data); }
};
......
......@@ -248,7 +248,7 @@ namespace dlib
void (T::*cb)(PARAM1)const
);
operator bool (
operator some_undefined_pointer_type (
) const;
bool operator! (
......@@ -315,7 +315,7 @@ namespace dlib
void (T::*cb)(PARAM1,PARAM2)const
);
operator bool (
operator some_undefined_pointer_type (
) const;
bool operator! (
......@@ -384,7 +384,7 @@ namespace dlib
void (T::*cb)(PARAM1,PARAM2,PARAM3)const
);
operator bool (
operator some_undefined_pointer_type (
) const;
bool operator! (
......@@ -455,7 +455,7 @@ namespace dlib
void (T::*cb)(PARAM1,PARAM2,PARAM3,PARAM4)const
);
operator bool (
operator some_undefined_pointer_type (
) const;
bool operator! (
......
......@@ -17,14 +17,14 @@ namespace dlib
typename PARAM3 = typename mfpb::param3_type,
typename PARAM4 = typename mfpb::param4_type
>
class member_function_pointer_kernel_c;
class mfpkc;
// ----------------------------------------------------------------------------------------
template <
typename mfpb
>
class member_function_pointer_kernel_c<mfpb,void,void,void,void> :
class mfpkc<mfpb,void,void,void,void> :
public mfpb
{
public:
......@@ -88,7 +88,7 @@ namespace dlib
typename mfpb,
typename PARAM1
>
class member_function_pointer_kernel_c<mfpb,PARAM1,void,void,void> :
class mfpkc<mfpb,PARAM1,void,void,void> :
public mfpb
{
public:
......@@ -154,7 +154,7 @@ namespace dlib
typename PARAM1,
typename PARAM2
>
class member_function_pointer_kernel_c<mfpb,PARAM1,PARAM2,void,void> :
class mfpkc<mfpb,PARAM1,PARAM2,void,void> :
public mfpb
{
public:
......@@ -222,7 +222,7 @@ namespace dlib
typename PARAM2,
typename PARAM3
>
class member_function_pointer_kernel_c<mfpb,PARAM1,PARAM2,PARAM3,void> :
class mfpkc<mfpb,PARAM1,PARAM2,PARAM3,void> :
public mfpb
{
public:
......@@ -292,7 +292,7 @@ namespace dlib
typename PARAM3,
typename PARAM4
>
class member_function_pointer_kernel_c :
class mfpkc :
public mfpb
{
public:
......
......@@ -122,11 +122,11 @@ namespace
mfp<int,int,int> a3, b3;
mfp<int,int,int,int> a4, b4;
member_function_pointer_kernel_c<mfp<> > a0c, b0c;
member_function_pointer_kernel_c<mfp<int> > a1c, b1c;
member_function_pointer_kernel_c<mfp<int,int> > a2c, b2c;
member_function_pointer_kernel_c<mfp<int,int,int> > a3c, b3c;
member_function_pointer_kernel_c<mfp<int,int,int,int> > a4c, b4c;
mfpkc<mfp<> > a0c, b0c;
mfpkc<mfp<int> > a1c, b1c;
mfpkc<mfp<int,int> > a2c, b2c;
mfpkc<mfp<int,int,int> > a3c, b3c;
mfpkc<mfp<int,int,int,int> > a4c, b4c;
DLIB_CASSERT(a0c == b0c, "");
DLIB_CASSERT(a1c == b1c, "");
......@@ -543,8 +543,8 @@ namespace
void perform_test (
)
{
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>();
member_function_pointer_kernel_test<mfpk1,mfp_test_helper>();
member_function_pointer_kernel_test<mfpk1,mfp_test_helper_const>();
}
} 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