Commit 768016e8 authored by Davis King's avatar Davis King

Upgraded the smart_ptr so that it can handle array pointers as well

as customer deleter functions.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%403107
parent 8e529bf0
......@@ -11,7 +11,32 @@
namespace dlib
{
template<typename T>
// ----------------------------------------------------------------------------------------
template <typename T>
struct default_deleter
{
void operator() (T* item) const
{
delete item;
}
};
template <typename T>
struct default_deleter<T[]>
{
void operator() (T* item) const
{
delete [] item;
}
};
// ----------------------------------------------------------------------------------------
template <
typename T,
typename deleter = default_deleter<T>
>
class scoped_ptr : noncopyable
{
/*!
......@@ -21,19 +46,31 @@ namespace dlib
public:
typedef T element_type;
typedef deleter deleter_type;
explicit scoped_ptr (
T* p = 0
) : ptr(p) { }
~scoped_ptr() { if (ptr) delete ptr; }
~scoped_ptr()
{
if (ptr)
{
deleter del;
del(ptr);
}
}
void reset (
T* p = 0
)
{
if (ptr)
delete ptr;
{
deleter del;
del(ptr);
}
ptr = p;
}
......@@ -81,17 +118,98 @@ namespace dlib
T* ptr;
};
// ----------------------------------------------------------------------------------------
template <
typename T,
typename deleter
>
class scoped_ptr<T[],deleter> : noncopyable
{
/*!
CONVENTION
- get() == ptr
!*/
public:
typedef T element_type;
explicit scoped_ptr (
T* p = 0
) : ptr(p) { }
~scoped_ptr()
{
if (ptr)
{
deleter del;
del(ptr);
}
}
void reset (
T* p = 0
)
{
if (ptr)
{
deleter del;
del(ptr);
}
ptr = p;
}
T& operator[] (
unsigned long idx
) const
{
DLIB_ASSERT(get() != 0,
"\tscoped_ptr::operator[]()"
<< "\n\tget() can't be null if you are going to dereference it"
<< "\n\tthis: " << this
);
return ptr[idx];
}
T* get() const
{
return ptr;
}
operator bool() const
{
return (ptr != 0);
}
void swap(
scoped_ptr& b
)
{
std::swap(ptr,b.ptr);
}
private:
T* ptr;
};
// ----------------------------------------------------------------------------------------
template <
typename T
typename T,
typename deleter
>
void swap(
scoped_ptr<T>& a,
scoped_ptr<T>& b
scoped_ptr<T,deleter>& a,
scoped_ptr<T,deleter>& b
)
{
a.swap(b);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_SCOPED_PTr_
......
......@@ -8,26 +8,65 @@
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <typename T>
struct default_deleter
{
void operator() (
T* item
) const;
/*!
ensures
- if (T is an array type (e.g. int[])) then
- performs "delete [] item;"
- else
- performs "delete item;"
!*/
};
// ----------------------------------------------------------------------------------------
template <
typename T
typename T,
typename deleter = default_deleter<T>
>
class scoped_ptr : noncopyable
{
/*!
REQUIREMENTS ON deleter
Must be a function object that performs deallocation of a pointer
of type T. For example, see the default_deleter type defined above.
INITIAL VALUE
defined by constructor
WHAT THIS OBJECT REPRESENTS
This is a implementation of the scoped_ptr class found in the Boost C++
library. It is a simple smart pointer class which guarantees that the
pointer contained within it will always be deleted.
This is a smart pointer class inspired by the implementation of the scoped_ptr
class found in the Boost C++ library. So this is a simple smart pointer
class which guarantees that the pointer contained within it will always be
deleted.
The class does not permit copying and so does not do any kind of
reference counting. Thus it is very simply and quite fast.
Note that this class allows you to use pointers to arrays as well as
pointers to single items. To let it know that it is supposed to point
to an array you have to declare it using the bracket syntax. Consider
the following examples:
// This is how you make a scoped pointer to a single thing
scoped_ptr<int> single_item(new int);
// This is how you can use a scoped pointer to contain array pointers.
// Note the use of []. This ensures that the proper version of delete
// is called.
scoped_ptr<int[]> array_of_ints(new int[50]);
!*/
public:
typedef T element_type;
typedef deleter deleter_type;
explicit scoped_ptr (
T* p = 0
......@@ -42,7 +81,9 @@ namespace dlib
/*!
ensures
- if (get() != 0) then
- calls delete get()
- calls deleter()(get())
(i.e. uses the deleter type to delete the pointer that is
contained in this scoped pointer)
!*/
void reset (
......@@ -51,7 +92,9 @@ namespace dlib
/*!
ensures
- if (get() != 0) then
- calls delete get()
- calls deleter()(get())
(i.e. uses the deleter type to delete the pointer that is
contained in this scoped pointer)
- #get() == p
(i.e. makes this object contain a pointer to p instead of whatever it
used to contain)
......@@ -62,6 +105,7 @@ namespace dlib
/*!
requires
- get() != 0
- T is NOT an array type (e.g. not int[])
ensures
- returns a reference to *get()
!*/
......@@ -71,10 +115,22 @@ namespace dlib
/*!
requires
- get() != 0
- T is NOT an array type (e.g. not int[])
ensures
- returns the pointer contained in this object
!*/
T& operator[](
unsigned long idx
) const;
/*!
requires
- get() != 0
- T is an array type (e.g. int[])
ensures
- returns get()[idx]
!*/
T* get(
) const;
/*!
......
......@@ -12,6 +12,27 @@
namespace
{
bool used_array_delete;
template <typename T>
struct test_deleter
{
void operator() (T* item) const
{
used_array_delete = false;
delete item;
}
};
template <typename T>
struct test_deleter<T[]>
{
void operator() (T* item) const
{
used_array_delete = true;
delete [] item;
}
};
using namespace test;
using namespace dlib;
......@@ -367,6 +388,32 @@ namespace
DLIB_TEST_MSG(counter == 0,counter);
DLIB_TEST_MSG(deleter_called == 3,counter);
{
scoped_ptr<int[]> a(new int[10]);
{
used_array_delete = false;
scoped_ptr<int[],test_deleter<int[]> > b(new int[10]);
for (int i = 0; i < 10; ++i)
{
a[i] = i;
b[i] = i;
}
}
DLIB_TEST(used_array_delete == true);
{
used_array_delete = true;
scoped_ptr<int,test_deleter<int> > c(new int);
}
DLIB_TEST(used_array_delete == false);
scoped_ptr<const int[]> const_a(new int[10]);
}
}
......
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