summaryrefslogtreecommitdiff
path: root/asl/maybe_uninit.hpp
blob: a69f39b7c5d46b180a0336715dbeede0431b48b9 (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
#pragma once

#include "asl/meta.hpp"
#include "asl/utility.hpp"
#include "asl/memory.hpp"

namespace asl
{

template<is_object T>
union maybe_uninit
{
private:
    T m_value;

public:
    constexpr maybe_uninit() requires trivially_default_constructible<T> = default;
    constexpr maybe_uninit() requires (!trivially_default_constructible<T>) {} // NOLINT

    template<typename... Args>
    explicit constexpr maybe_uninit(in_place_t, Args&&... args)
        requires constructible_from<T, Args&&...>
        : m_value{ASL_FWD(args)...}
    {}

    constexpr maybe_uninit(const maybe_uninit&) requires trivially_copy_constructible<T> = default;
    constexpr maybe_uninit(const maybe_uninit&) requires (!trivially_copy_constructible<T>) {} // NOLINT

    constexpr maybe_uninit(maybe_uninit&&) requires trivially_move_constructible<T> = default;
    constexpr maybe_uninit(maybe_uninit&&) requires (!trivially_move_constructible<T>) {} // NOLINT

    constexpr maybe_uninit& operator=(const maybe_uninit&) requires trivially_copy_assignable<T> = default;
    constexpr maybe_uninit& operator=(const maybe_uninit&) requires (!trivially_copy_assignable<T>) {}

    constexpr maybe_uninit& operator=(maybe_uninit&&) requires trivially_move_assignable<T> = default;
    constexpr maybe_uninit& operator=(maybe_uninit&&) requires (!trivially_move_assignable<T>) {}

    constexpr ~maybe_uninit() requires trivially_destructible<T> = default;
    constexpr ~maybe_uninit() requires (!trivially_destructible<T>) {} // NOLINT

    // @Safety Value must not have been initialized yet
    template<typename... Args>
    constexpr void construct_unsafe(Args&&... args)
        requires constructible_from<T, Args&&...>
    {
        construct_at<T>(&m_value, ASL_FWD(args)...);
    }

    // @Safety Value must have been initialized
    template<typename U>
    constexpr void assign_unsafe(U&& value)
        requires assignable_from<T&, U&&>
    {
        m_value = ASL_FWD(value);
    }

    // @Safety Value must have been initialized
    constexpr void destroy_unsafe()
    {
        if constexpr (!trivially_destructible<T>)
        {
            destroy(&m_value);
        }
    }

    // @Safety Value must have been initialized
    constexpr const T& as_init_unsafe() const& { return m_value; }
    constexpr T&       as_init_unsafe() &      { return m_value; }
    constexpr T&&      as_init_unsafe() &&     { return ASL_MOVE(m_value); }
};

} // namespace asl