понедельник, 27 июня 2011 г.

Умный указатель.

Реализация умного указателя, написанная под влиянием книги Александреску.
#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;
}

Комментариев нет:

Отправить комментарий