summaryrefslogtreecommitdiff
path: root/AK/MaybeOwned.h
blob: cc280ea0a39aa0ae28c7e04b1575a08d857aa40a (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
/*
 * Copyright (c) 2022, Tim Schumacher <timschumi@gmx.de>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/NonnullOwnPtr.h>
#include <AK/Variant.h>

namespace AK {

template<typename T>
class MaybeOwned {
public:
    template<DerivedFrom<T> U>
    MaybeOwned(NonnullOwnPtr<U> handle)
        : m_handle(adopt_own<T>(*handle.leak_ptr()))
    {
    }

    // This is made `explicit` to not accidentally create a non-owning MaybeOwned,
    // which may not always be intended.
    explicit MaybeOwned(T& handle)
        : m_handle(&handle)
    {
    }

    T* ptr()
    {
        if (m_handle.template has<T*>())
            return m_handle.template get<T*>();
        else
            return m_handle.template get<NonnullOwnPtr<T>>();
    }

    T const* ptr() const
    {
        if (m_handle.template has<T*>())
            return m_handle.template get<T*>();
        else
            return m_handle.template get<NonnullOwnPtr<T>>();
    }

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

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

private:
    Variant<NonnullOwnPtr<T>, T*> m_handle;
};

}

#if USING_AK_GLOBALLY
using AK::MaybeOwned;
#endif