The interface and some of the implementation is take from Boost. However, it is intended to be transferable between projects by only copying one file. I have removed most of the policy classes in favor of more condensed code that requires less files to move around. Please tell me where my strengths are as well as where the code might fall apart.
unique_ptr.h -- Interface and Some Implementation
#ifndef UNIQUE_PTR_HPP_INCLUDED
#define UNIQUE_PTR_HPP_INCLUDED
namespace glext
{
template<class T>
struct deleter
{
static void release(T *p)
{
if (p) {
delete p;
p = 0;
}
}
};
template<class T>
struct array_deleter
{
static void release(T *p)
{
if (p) {
delete [] p;
p = 0;
}
}
};
template <class T, class D = glext::deleter<T> >
class unique_ptr
{
private:
T *_ptr;
template <class U, class D> unique_ptr(unique_ptr<U, D> &);
template <class U, class D> unique_ptr &operator=(unique_ptr<U, D> &);
public:
typedef T element_type;
typedef D deleter_type;
unique_ptr();
explicit unique_ptr(T *p);
~unique_ptr();
unique_ptr &operator=(unique_ptr u);
template <class U>
unique_ptr &operator=(unique_ptr<U, D> u);
T operator*() const;
T *operator->() const;
T *get() const;
T *release();
void reset(T *p = 0);
void swap(unique_ptr &u);
};
}
#include "unique_ptr.inl"
unique_ptr.inl -- Implementation
namespace glext
{
template <class T, class D>
unique_ptr<T, D>::unique_ptr() :
_ptr(0)
{}
template <class T, class D>
unique_ptr<T, D>::unique_ptr(T *p) :
_ptr(p)
{}
template <class T, class D>
unique_ptr<T, D>::~unique_ptr()
{
reset();
}
template <class T, class D>
unique_ptr<T, D> &unique_ptr<T, D>::operator=(unique_ptr<T, D> u)
{
reset(u.release());
return *this;
}
template <class T, class D>
template <class U>
unique_ptr<T, D> &unique_ptr<T, D>::operator=(unique_ptr<U, D> u)
{
reset(u.release());
return *this;
}
template <class T, class D>
T unique_ptr<T, D>::operator*() const
{
return *_ptr;
}
template <class T, class D>
T *unique_ptr<T, D>::operator->() const
{
return _ptr;
}
template <class T, class D>
T *unique_ptr<T, D>::get() const
{
return *_ptr;
}
template <class T, class D>
T *unique_ptr<T, D>::release()
{
T *tmp = _ptr;
_ptr = 0;
return tmp;
}
template <class T, class D>
void unique_ptr<T, D>::reset(T *p = 0)
{
if (_ptr != p) {
if (_ptr) {
unique_ptr<T, D>::deleter_type::release(_ptr);
_ptr = p;
}
}
}
template <class T, class D>
void swap(unique_ptr<T, D> &u)
{
std::swap(_ptr., u._ptr);
}
template <class T, class D>
inline void swap(unique_ptr<T, D> &x, unique_ptr<T, D> &y)
{
x.swap(y);
}
template <class T1, class D1, class T2, class D2>
bool operator==(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
{
return x.get() == y.get();
}
template <class T1, class D1, class T2, class D2>
bool operator!=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
{
return x.get() != y.get();
}
template <class T1, class D1, class T2, class D2>
bool operator<(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
{
return x.get() < y.get();
}
template <class T1, class D1, class T2, class D2>
bool operator<=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
{
return x.get() <= y.get();
}
template <class T1, class D1, class T2, class D2>
bool operator>(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
{
return x.get() > y.get();
}
template <class T1, class D1, class T2, class D2>
bool operator>=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
{
return x.get() >= y.get();
}
}
Sample usage
int main(int /*argc*/, char * /*argv*/[]) {
alloc_console();
glext::unique_ptr<int> uptr(new int(20));
glext::unique_ptr<int, glext::array_deleter<int> > uaptr(new int[20]);
}
std::move
with the new std::unique_ptr. Why not install boost when you install the compiler. Its not as if that is uncommon. Why would you want to copy the header files around. You don't even need to build boost (the smart pointers are part of the header only libraries). \$\endgroup\$