HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
not_null.hpp
1// Copyright Take Vos 2023.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "assert.hpp"
8#include "misc.hpp"
9#include "type_traits.hpp"
10#include "concepts.hpp"
11#include "terminate.hpp"
12#include "../macros.hpp"
13#include <type_traits>
14#include <memory>
15#include <concepts>
16
17hi_export_module(utility.not_null);
18
19hi_export namespace hi { inline namespace v1 {
20
21template<nullable_pointer T>
22class not_null {
23public:
24 using element_type = std::pointer_traits<T>::element_type;
25 using pointer = element_type *;
26 using reference = element_type &;
27
28 ~not_null() = default;
29 not_null() = delete;
30 not_null(nullptr_t) = delete;
31 not_null &operator=(nullptr_t) = delete;
32
33 not_null(std::in_place_t, T &&o) noexcept : _p(std::move(o)) {}
34
35 template<nullable_pointer O>
36 not_null(not_null<O> const &o) noexcept
37 requires requires { this->_p = o._p; }
38 : _p(o._p)
39 {
40 }
41
42 template<nullable_pointer O>
43 not_null &operator=(not_null<O> const &o) noexcept
44 requires requires { this->_p = o._p; }
45 {
46 if constexpr (std::same_as<std::remove_cvref_t<decltype(*this)>, std::remove_cvref_t<decltype(o)>>) {
47 if (this == std::addressof(o)) {
48 return *this;
49 }
50 }
51
52 _p = o._p;
53 return *this;
54 }
55
56 template<nullable_pointer O>
57 not_null(not_null<O> &&o) noexcept
58 requires requires { this->_p = std::move(o._p); }
59 : _p(std::move(o._p))
60 {
61 }
62
63 template<nullable_pointer O>
64 not_null &operator=(not_null<O> &&o) noexcept
65 requires requires { this->_p = std::move(o._p); }
66 {
67 if constexpr (std::same_as<std::remove_cvref_t<decltype(*this)>, std::remove_cvref_t<decltype(o)>>) {
68 if (this == std::addressof(o)) {
69 return *this;
70 }
71 }
72
73 _p = std::move(o._p);
74 return *this;
75 }
76
77 template<nullable_pointer O>
78 not_null(O &&o) noexcept
79 requires requires { this->_p = std::forward<O>(o); } :
80 _p(std::forward<O>(o))
81 {
82 hi_assert_not_null(_p);
83 }
84
85 template<nullable_pointer O>
86 not_null &operator=(O &&o) noexcept
87 requires requires { this->_p = std::forward<O>(o); }
88 {
89 hi_assert_not_null(o);
90 _p = std::forward<O>(o);
91 return *this;
92 }
93
94 // XXX: due to a bug in the standard you can not create a reference
95 // qualifier overload set (ambiguity). To be able to properly use
96 // not_null<std::unique_ptr<T>> we will need return a rvalue reference
97 // when this is a rvalue reference, this can only be done using
98 // C++23 deducing this.
99
100 operator T() const noexcept
101 {
102 return _p;
103 }
104
105 [[nodiscard]] pointer get() const noexcept
106 {
107 auto const r = [this]{
108 if constexpr (std::is_pointer_v<T>) {
109 return _p;
110 } else {
111 return _p.get();
112 }
113 }();
114
115 hi_assume(r != nullptr);
116 return r;
117 }
118
119 [[deprecated("not_null<> pointers are always true")]] explicit operator bool() const noexcept
120 {
121 return true;
122 }
123
124 [[deprecated("not_null<> pointers are never equal to nullptr")]] [[nodiscard]] bool operator==(nullptr_t) const noexcept
125 {
126 return false;
127 }
128
129 [[nodiscard]] reference operator*() const noexcept
130 {
131 return *_p;
132 }
133
134 [[nodiscard]] pointer operator->() const noexcept
135 {
136 return get();
137 }
138
139private:
140 T _p;
141
142 template<nullable_pointer T>
143 friend class not_null;
144};
145
146template<typename T, typename... Args>
147[[nodiscard]] not_null<std::unique_ptr<T>> make_unique_not_null(Args &&... args)
148{
149 return not_null<std::unique_ptr<T>>{std::in_place, std::make_unique<T>(std::forward<Args>(args)...)};
150}
151
152template<typename T, typename... Args>
153[[nodiscard]] not_null<std::shared_ptr<T>> make_shared_not_null(Args &&... args)
154{
155 return not_null<std::shared_ptr<T>>{std::in_place, std::make_shared<T>(std::forward<Args>(args)...)};
156}
157
158template<typename T>
159[[nodiscard]] not_null<T *> make_not_null(T *ptr) noexcept
160{
161 return not_null<T *>{ptr};
162}
163
164template<typename T>
165[[nodiscard]] not_null<T *> make_not_null(T &ptr) noexcept
166{
167 return not_null<T *>{std::in_place, std::addressof(ptr)};
168}
169
170template<typename T>
171[[nodiscard]] not_null<T *> make_not_null(T &&ptr) noexcept = delete;
172
173}} // namespace hi::v1
Utilities to assert and bound check.
Utilities for throwing exceptions and terminating the application.
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
The HikoGUI namespace.
Definition recursive_iterator.hpp:15
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:378
Definition not_null.hpp:22
T addressof(T... args)
T move(T... args)