scoped_array.h 3.23 KB
Newer Older
gejun's avatar
gejun committed
1 2 3 4 5 6
// Copyright (c) 2013, The TOFT Authors.
// All rights reserved.
//
// Author: CHEN Feng <chen3feng@gmail.com>
// Created: 2013-03-02

7 8
#ifndef BUTIL_SCOPED_ARRAY_H
#define BUTIL_SCOPED_ARRAY_H
gejun's avatar
gejun committed
9 10 11 12

#include <assert.h>
#include <stddef.h>

13
namespace butil {
gejun's avatar
gejun committed
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

// 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&);
};

111
} // namespace butil
gejun's avatar
gejun committed
112

113
#endif // BUTIL_SCOPED_ARRAY_H