#include <cassert>
#include <iostream>
#include <vector>
template <typename T> class ElementStorageStrategy;
template <typename T> class ArrayStorageStrategy;
template <typename T, template <typename T> class StorageStrategy>
class NoCopyingOwnershipStrategy;
template <typename T, template <typename T> class StorageStrategy>
class CounterSimpleOwnershipStrategy;
template <typename T, template <typename T> class StorageStrategy>
class CounterListOwnershipStrategy;
template <typename T, template <typename T> class StorageStrategy>
class DestructiveCopyingOwnershipStrategy;
template <typename T,
template <typename T> class StorageStrategy = ElementStorageStrategy,
template <typename T, template <typename T> class StorageStrategy >
class OwnershipStrategy = NoCopyingOwnershipStrategy>
class SmartPointer {
private:
T* pointer_;
OwnershipStrategy<T, StorageStrategy > ownership_;
public:
SmartPointer() {}
explicit SmartPointer(T* pointer) : pointer_(pointer) {}
SmartPointer(SmartPointer& other) {
pointer_ = NULL;
ownership_.Assign(*this, other);
}
SmartPointer& operator=(const SmartPointer& other) {
if (pointer_ != other.pointer_) {
ownership_.Assign(*this, other);
}
return *this;
}
// Ambigious casting to prevent delete:
operator T*() {
return pointer_;
}
operator void*() {
return pointer_;
}
// Comparsion operators:
bool operator!() const { // For cases "if (!sp) ..."
return pointer_ == 0;
}
inline friend bool operator==(const SmartPointer& lhs,
const SmartPointer& rhs) {
return lhs.pointer_ == rhs.pointer_;
}
inline friend bool operator==(const SmartPointer& lhs, const T* rhs) {
return lhs.pointer_ == rhs;
}
inline friend bool operator==(const T* lhs, const SmartPointer& rhs) {
return lhs == rhs.pointer_;
}
inline friend bool operator!=(const SmartPointer& lhs,
const SmartPointer& rhs) {
return lhs.pointer_ != rhs.pointer_;
}
inline friend bool operator!=(const SmartPointer& lhs, const T* rhs) {
return lhs.pointer_ != rhs;
}
inline friend bool operator!=(const T* lhs, const SmartPointer& rhs) {
return lhs != rhs.pointer_;
}
// And template comparsion operators for cases like:
//
// SmartPointer<Base> sp;
// Derived* p;
// ...
// if (sp == p) {}
template <typename R>
inline friend bool operator==(const SmartPointer& lhs, const R* rhs) {
return lhs.pointer_ == rhs;
}
template <typename R>
inline friend bool operator==(const R* lhs, const SmartPointer& rhs) {
return lhs == rhs.pointer_;
}
template <typename R>
inline friend bool operator!=(const SmartPointer& lhs, const R* rhs) {
return lhs.pointer_ != rhs;
}
template <typename R>
inline friend bool operator!=(const R* lhs, const SmartPointer& rhs) {
return lhs != rhs.pointer_;
}
~SmartPointer() {
ownership_.Release(*this);
}
T& operator*() const {
return *pointer_;
}
T* operator->() const {
return pointer_;
}
friend T* GetImplPtr(SmartPointer& sp) {
return sp.pointer_;
}
friend void SetImplPtr(SmartPointer& dst, SmartPointer& src) {
dst.pointer_ = src.pointer_;
}
friend void SetImplPtr(SmartPointer& sp, T* ptr) {
sp.pointer_ = ptr;
}
friend OwnershipStrategy<T, StorageStrategy>& GetImplOwn(SmartPointer& sp) {
return sp.ownership_;
}
};
template <typename T>
class ElementStorageStrategy {
public:
static void Delete(T* ptr) {
delete ptr;
}
};
template <typename T>
class ArrayStorageStrategy {
public:
static void Delete(T* ptr) {
delete[] ptr;
}
};
template <typename T, template <typename T> class StorageStrategy>
class NoCopyingOwnershipStrategy {
public:
// Assign is not defined because it is prohibited in this strategy.
void Assign(SmartPointer<T, StorageStrategy,
NoCopyingOwnershipStrategy>& dst,
SmartPointer<T, StorageStrategy,
NoCopyingOwnershipStrategy>& src);
void Release(SmartPointer<T, StorageStrategy,
NoCopyingOwnershipStrategy>& smart_ptr) {
StorageStrategy<T>::Delete(GetImplPtr(smart_ptr));
}
};
template <typename T, template <typename T> class StorageStrategy>
class CounterSimpleOwnershipStrategy {
private:
unsigned int* counter_;
public:
CounterSimpleOwnershipStrategy() : counter_(new unsigned int(1)) {}
void Assign(SmartPointer<T, StorageStrategy,
CounterSimpleOwnershipStrategy>& dst,
SmartPointer<T, StorageStrategy,
CounterSimpleOwnershipStrategy>& src) {
SetImplPtr(dst, src);
++*(GetImplOwn(src).counter_);
delete GetImplOwn(dst).counter_;
GetImplOwn(dst).counter_ = GetImplOwn(src).counter_;
}
void Release(SmartPointer<T, StorageStrategy,
CounterSimpleOwnershipStrategy>& smart_ptr) {
if (--*(GetImplOwn(smart_ptr).counter_) == 0) {
StorageStrategy<T>::Delete(GetImplPtr(smart_ptr));
delete counter_;
}
}
};
template <typename T, template <typename T> class StorageStrategy>
class CounterListOwnershipStrategy {
private:
CounterListOwnershipStrategy<T, StorageStrategy> *prev_, *next_;
public:
CounterListOwnershipStrategy() : prev_(NULL), next_(NULL) {}
void Assign(SmartPointer<T, StorageStrategy,
CounterListOwnershipStrategy>& dst,
SmartPointer<T, StorageStrategy,
CounterListOwnershipStrategy>& src) {
CounterListOwnershipStrategy<T, StorageStrategy> *last_ptr =
&(GetImplOwn(src));
while (last_ptr->next_ != NULL) {
last_ptr = last_ptr->next_;
}
last_ptr->next_ = this;
if (prev_ != NULL) {
prev_->next_ = next_;
}
if (next_ != NULL) {
next_->prev_ = prev_;
}
prev_ = last_ptr;
next_ = NULL;
SetImplPtr(dst, src);
}
void Release(SmartPointer<T, StorageStrategy,
CounterListOwnershipStrategy>& smart_ptr) {
CounterListOwnershipStrategy<T, StorageStrategy> *own_ptr =
&GetImplOwn(smart_ptr);
if (own_ptr->prev_ == NULL && own_ptr->next_ == NULL) {
StorageStrategy<T>::Delete(GetImplPtr(smart_ptr));
}
if (own_ptr->prev_ != NULL) {
own_ptr->prev_->next_ = own_ptr->next_;
}
if (own_ptr->next_ != NULL) {
own_ptr->next_->prev_ = own_ptr->prev_;
}
}
};
template <typename T, template <typename T> class StorageStrategy>
class DestructiveCopyingOwnershipStrategy {
public:
void Assign(SmartPointer<T, StorageStrategy,
DestructiveCopyingOwnershipStrategy>& dst,
SmartPointer<T, StorageStrategy,
DestructiveCopyingOwnershipStrategy>& src) {
StorageStrategy<T>::Delete(GetImplPtr(dst));
SetImplPtr(dst, src);
SetImplPtr(src, NULL);
}
void Release(SmartPointer<T, StorageStrategy,
DestructiveCopyingOwnershipStrategy>& smart_ptr) {
StorageStrategy<T>::Delete(GetImplPtr(smart_ptr));
}
};
int main() {
// Tests
// NoCopyingOwnershipStrategy:
std::cout << "Testing NoCopyingOwnershipStrategy...";
{
int *my_int = new int(24);
SmartPointer<int> sp1(new int(42));
SmartPointer<int> sp2(my_int);
assert(*sp1 == 42);
assert(*sp2 == *my_int);
assert(sp1 != sp2);
}
std::cout << "done" << std::endl;
// CounterSimpleOwnershipStrategy:
std::cout << "Testing CounterSimpleOwnershipStrategy...";
{
SmartPointer<int,
ElementStorageStrategy,
CounterSimpleOwnershipStrategy> sp1(new int(42));
SmartPointer<int,
ElementStorageStrategy,
CounterSimpleOwnershipStrategy> sp2(sp1);
assert(*sp1 == 42);
assert(sp1 == sp2);
std::vector<SmartPointer<int, ElementStorageStrategy,
CounterSimpleOwnershipStrategy>*> my_vec;
for (int i = 0; i < 1000; ++i) {
my_vec.push_back(new SmartPointer<int, ElementStorageStrategy,
CounterSimpleOwnershipStrategy>(new int(i)));
}
for (int i = 0; i < 1000; ++i) {
delete my_vec[i];
}
}
std::cout << "done" << std::endl;
// CounterListOwnershipStrategy:
std::cout << "Testing CounterListOwnershipStrategy...";
{
SmartPointer<int,
ElementStorageStrategy,
CounterListOwnershipStrategy> sp1(new int(42));
SmartPointer<int,
ElementStorageStrategy,
CounterListOwnershipStrategy> sp2(sp1);
assert(*sp1 == 42);
assert(sp1 == sp2);
std::vector<SmartPointer<int, ElementStorageStrategy,
CounterListOwnershipStrategy>*> my_vec;
for (int i = 0; i < 1000; ++i) {
my_vec.push_back(new SmartPointer<int, ElementStorageStrategy,
CounterListOwnershipStrategy>(new int(i)));
}
for (int i = 0; i < 1000; ++i) {
delete my_vec[i];
}
}
std::cout << "done" << std::endl;
// DestructiveCopyingOwnershipStrategy
std::cout << "Testing DestructiveCopyingOwnershipStrategy...";
{
SmartPointer<int,
ElementStorageStrategy,
DestructiveCopyingOwnershipStrategy> sp1(new int(42));
SmartPointer<int,
ElementStorageStrategy,
DestructiveCopyingOwnershipStrategy> sp2(sp1);
assert(sp2 != sp1);
assert(!sp1);
}
std::cout << "done" << std::endl;
std::cout << "All tests successfully passed." << std::endl;
return 0;
}
понедельник, 27 июня 2011 г.
Умный указатель.
Реализация умного указателя, написанная под влиянием книги Александреску.
Подписаться на:
Комментарии к сообщению (Atom)
Комментариев нет:
Отправить комментарий