From cbf5c721f42e1c4b2caaf5f55395c68639783b28 Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 17 Mar 2011 23:28:33 -0300 Subject: [PATCH] Add UniquePtr class. --- src/base/unique_ptr.h | 84 +++++++++++++++++++++++++++++ src/base/unique_ptr_unittest.cpp | 91 ++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 src/base/unique_ptr.h create mode 100644 src/base/unique_ptr_unittest.cpp diff --git a/src/base/unique_ptr.h b/src/base/unique_ptr.h new file mode 100644 index 000000000..48ea7dfd2 --- /dev/null +++ b/src/base/unique_ptr.h @@ -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 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 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 diff --git a/src/base/unique_ptr_unittest.cpp b/src/base/unique_ptr_unittest.cpp new file mode 100644 index 000000000..25fa348a7 --- /dev/null +++ b/src/base/unique_ptr_unittest.cpp @@ -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 + +#include "base/unique_ptr.h" + +TEST(UniquePtr, DefaultCtor) +{ + UniquePtr 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 a(new int(5)); + EXPECT_EQ(5, *a); +} + +TEST(UniquePtr, CopyValues) +{ + UniquePtr a(new int(3)); + UniquePtr 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(new A(100)); + { + UniquePtr b(new A(200)); + { + UniquePtr 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 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(); +}