// Copyright (c) 2013, The TOFT Authors. // All rights reserved. // // Author: CHEN Feng <chen3feng@gmail.com> // Created: 2013-03-02 #ifndef BUTIL_SCOPED_ARRAY_H #define BUTIL_SCOPED_ARRAY_H #include <assert.h> #include <stddef.h> namespace butil { // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate // with new [] and the destructor deletes objects with delete []. // // As with scoped_ptr<C>, a scoped_array<C> either points to an object // or is NULL. A scoped_array<C> owns the object that it points to. // // Size: sizeof(scoped_array<C>) == sizeof(C*) template <class C> class scoped_array { public: // The element type typedef C element_type; // Constructor. Defaults to intializing with NULL. // There is no way to create an uninitialized scoped_array. // The input parameter must be allocated with new []. explicit scoped_array(C* p = NULL) : array_(p) { } // Destructor. If there is a C object, delete it. // We don't need to test ptr_ == NULL because C++ does that for us. ~scoped_array() { enum { type_must_be_complete = sizeof(C) }; delete[] array_; array_ = reinterpret_cast<C*>(-1); } // implicit cast to bool operator void*() const { return array_; } bool operator!() const { return array_ == 0; } // Reset. Deletes the current owned object, if any. // Then takes ownership of a new object, if given. // this->reset(this->get()) works. void reset(C* p = NULL) { if (p != array_) { enum { type_must_be_complete = sizeof(C) }; delete[] array_; array_ = p; } } // Get one element of the current object. // Will assert() if there is no current object, or index i is negative. C& operator[](std::ptrdiff_t i) const { assert(i >= 0); assert(array_ != NULL); return array_[i]; } // Get a pointer to the zeroth element of the current object. // If there is no current object, return NULL. C* get() const { return array_; } // Comparison operators. // These return whether two scoped_array refer to the same object, not just to // two different but equal objects. bool operator==(C* p) const { return array_ == p; } bool operator!=(C* p) const { return array_ != p; } // Swap two scoped arrays. void swap(scoped_array& p2) { C* tmp = array_; array_ = p2.array_; p2.array_ = tmp; } // Release an array. // The return value is the current pointer held by this object. // If this object holds a NULL pointer, the return value is NULL. // After this operation, this object will hold a NULL pointer, // and will not own the object any more. C* release() { C* retVal = array_; array_ = NULL; return retVal; } private: C* array_; // Forbid comparison of different scoped_array types. template <class C2> bool operator==(scoped_array<C2> const& p2) const; template <class C2> bool operator!=(scoped_array<C2> const& p2) const; // Disallow evil constructors scoped_array(const scoped_array&); void operator=(const scoped_array&); }; } // namespace butil #endif // BUTIL_SCOPED_ARRAY_H