summaryrefslogtreecommitdiff
path: root/Libraries/LibCore/ObjectPtr.h
blob: a34c8f82248d84f85fa1b4d720b357bc4b08d1bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
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
#pragma once

#include <AK/StdLibExtras.h>

// This is a stopgap pointer. It's not meant to stick around forever.

template<typename T>
class ObjectPtr {
public:
    ObjectPtr() {}
    ObjectPtr(T* ptr)
        : m_ptr(ptr)
    {
    }
    ObjectPtr(T& ptr)
        : m_ptr(&ptr)
    {
    }
    ~ObjectPtr()
    {
        if (m_ptr && !m_ptr->parent())
            delete m_ptr;
    }

    template<typename U>
    ObjectPtr(U* ptr)
        : m_ptr(static_cast<T*>(ptr))
    {
    }

    ObjectPtr(const ObjectPtr& other)
        : m_ptr(other.m_ptr)
    {
    }

    template<typename U>
    ObjectPtr(const ObjectPtr<U>& other)
        : m_ptr(static_cast<T*>(const_cast<ObjectPtr<U>&>(other).ptr()))
    {
    }

    ObjectPtr(ObjectPtr&& other)
    {
        m_ptr = other.leak_ptr();
    }

    template<typename U>
    ObjectPtr(const ObjectPtr<U>&& other)
    {
        m_ptr = static_cast<T*>(const_cast<ObjectPtr<U>&>(other).leak_ptr());
    }

    ObjectPtr& operator=(const ObjectPtr& other)
    {
        m_ptr = other.m_ptr;
        return *this;
    }

    ObjectPtr& operator=(ObjectPtr&& other)
    {
        if (this != &other) {
            m_ptr = exchange(other.m_ptr, nullptr);
        }
        return *this;
    }

    T* operator->() { return m_ptr; }
    const T* operator->() const { return m_ptr; }

    operator T*() { return m_ptr; }
    operator const T*() const { return m_ptr; }

    T& operator*() { return *m_ptr; }
    const T& operator*() const { return *m_ptr; }

    T* ptr() const { return m_ptr; }
    T* leak_ptr() { return exchange(m_ptr, nullptr); }

private:
    T* m_ptr { nullptr };
};