Add UniquePtr class.

This commit is contained in:
David Capello 2011-03-17 23:28:33 -03:00
parent 55c611c08b
commit cbf5c721f4
2 changed files with 175 additions and 0 deletions

84
src/base/unique_ptr.h Normal file
View File

@ -0,0 +1,84 @@
// ASE base library
// Copyright (C) 2001-2011 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef BASE_UNIQUE_PTR_H_INCLUDED
#define BASE_UNIQUE_PTR_H_INCLUDED
#include "base/disable_copying.h"
// Default deleter used by unique pointers (it calls "delete" operator).
template<class T>
class DefaultUniquePtrDeleter
{
public:
void operator()(T* ptr)
{
delete ptr;
}
};
// Keeps the life time of the pointee object between the scope of the
// UniquePtr instance.
template<class T, class D = DefaultUniquePtrDeleter<T> >
class UniquePtr
{
public:
typedef T* pointer;
typedef T element_type;
typedef D deleter_type;
UniquePtr()
: m_ptr(pointer())
{
}
// Constructor with default deleter.
explicit UniquePtr(pointer ptr)
: m_ptr(ptr)
{
}
// Constructor with customized deleter.
UniquePtr(pointer ptr, deleter_type deleter)
: m_ptr(ptr)
, m_deleter(deleter)
{
}
// Releases one reference from the pointee.
~UniquePtr()
{
if (m_ptr)
m_deleter(m_ptr);
}
void reset(pointer ptr = pointer())
{
if (m_ptr)
m_deleter(m_ptr);
m_ptr = ptr;
}
pointer release()
{
pointer ptr(m_ptr);
m_ptr = pointer();
return ptr;
}
pointer get() const { return m_ptr; }
element_type& operator*() const { return *m_ptr; }
pointer operator->() const { return m_ptr; }
operator pointer() const { return m_ptr; }
private:
pointer m_ptr; // The pointee object.
deleter_type m_deleter; // The deleter.
DISABLE_COPYING(UniquePtr);
};
#endif

View File

@ -0,0 +1,91 @@
// ASE base library
// Copyright (C) 2001-2011 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#include <gtest/gtest.h>
#include "base/unique_ptr.h"
TEST(UniquePtr, DefaultCtor)
{
UniquePtr<int> a;
EXPECT_TRUE(NULL == a.get());
a.reset(new int(2));
ASSERT_TRUE(NULL != a.get());
EXPECT_TRUE(2 == *a);
a.reset();
EXPECT_TRUE(NULL == a.get());
}
TEST(UniquePtr, IntPtr)
{
UniquePtr<int> a(new int(5));
EXPECT_EQ(5, *a);
}
TEST(UniquePtr, CopyValues)
{
UniquePtr<int> a(new int(3));
UniquePtr<int> b(new int(4));
EXPECT_EQ(3, *a);
EXPECT_EQ(4, *b);
*a = *b;
EXPECT_EQ(4, *a);
EXPECT_EQ(4, *b);
}
int valueInDtor;
class A
{
int m_value;
public:
A(int value) : m_value(value) { }
~A() { valueInDtor = m_value; }
};
TEST(UniquePtr, PtrToStruct)
{
valueInDtor = 0;
{
UniquePtr<A> a(new A(100));
{
UniquePtr<A> b(new A(200));
{
UniquePtr<A> c(new A(300));
EXPECT_EQ(0, valueInDtor);
c.reset();
EXPECT_EQ(300, valueInDtor);
c.reset(new A(400));
}
EXPECT_EQ(400, valueInDtor);
}
EXPECT_EQ(200, valueInDtor);
}
EXPECT_EQ(100, valueInDtor);
}
TEST(UniquePtr, Release)
{
UniquePtr<int> a(new int(5));
EXPECT_EQ(5, *a);
int* ptr = a.release();
delete ptr;
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}