libhatchet
Loading...
Searching...
No Matches
hxoptional.hpp
Go to the documentation of this file.
1#pragma once
2// SPDX-FileCopyrightText: © 2017-2026 Adrian Johnston.
3// SPDX-License-Identifier: MIT
4// This file is licensed under the MIT license found in the LICENSE.md file.
5
9
10#include "libhatchet.h"
11
12// HX_USE_MACROS_WITH_MODULE allows including macros alongside the module.
13#if HX_USE_MACROS_WITH_MODULE
14#error Header does not provide macros alone.
15#endif
16
17#include "hxutility.h"
18#include "hxkey.hpp"
19
20HX_NS_BEGIN_
21
23template<typename T_> class hxoptional;
24
25namespace hxdetail_ {
26// Used to prevent forwarding constructors from hijacking converting-copy
27// construction paths.
28template<typename> struct hxis_hxoptional_ : hxfalse_t { };
29template<typename U_> struct hxis_hxoptional_<hxoptional<U_>> : hxtrue_t { };
30}
32
35 // GCOVR_EXCL_START
37 explicit constexpr hxnullopt_t(int) { }
38 // GCOVR_EXCL_STOP
39};
40
44
51template<typename T_>
53public:
54 // These are for safety. Use hxref for pointer and reference types.
55 static_assert(!hxis_reference<T_>::value, "hxoptional does not support reference types");
56 static_assert(!hxis_pointer<T_>::value, "hxoptional does not support pointer types");
57
60 using value_type = T_;
61
63 hxoptional(void) : m_engaged_(false) { }
64
67 hxoptional(hxnullopt_t) : m_engaged_(false) { }
68
71 hxoptional(const hxoptional& other_) noexcept;
72
76 hxoptional(hxoptional&& other_) noexcept;
77
81 template<typename U_>
82 hxoptional(const hxoptional<U_>& other_) noexcept;
83
88 template<typename U_>
89 hxoptional(hxoptional<U_>&& other_) noexcept;
90
93 template<typename U_=T_, hxenable_if_t<
94 !hxdetail_::hxis_hxoptional_<hxremove_cvref_t<U_>>::value, bool> = true>
95 hxoptional(U_&& value_) noexcept;
96
98 ~hxoptional(void) { reset(); }
99
103
106 hxattr_nodiscard const T_& operator*(void) const;
107
110
113 hxattr_nodiscard const T_* operator->(void) const;
114
116 hxattr_nodiscard operator bool(void) const { return m_engaged_; }
117
120 hxoptional& operator=(const hxoptional& other_) noexcept;
121
125 hxoptional& operator=(hxoptional&& other_) noexcept;
126
129 hxoptional& operator=(hxnullopt_t) { reset(); return *this; }
130
133 template<typename U_=T_, hxenable_if_t<
134 !hxdetail_::hxis_hxoptional_<hxremove_cvref_t<U_>>::value, bool> = true>
135 hxoptional& operator=(U_&& value_) noexcept;
136
140 template<typename U_>
141 hxoptional& operator=(const hxoptional<U_>& other_) noexcept;
142
146 template<typename U_>
148
152 hxattr_nodiscard bool operator==(const hxoptional& rhs_) const;
153
156 hxattr_nodiscard bool operator==(hxnullopt_t) const { return !m_engaged_; }
157
160 hxattr_nodiscard bool operator==(const T_& value_) const;
161
162#if HX_CPLUSPLUS < 202002L // C++20 defaults != from ==.
165 hxattr_nodiscard bool operator!=(const hxoptional& rhs_) const { return !(*this == rhs_); }
166
169 hxattr_nodiscard bool operator!=(hxnullopt_t nullopt_) const { return !(*this == nullopt_); }
170
174 hxattr_nodiscard bool operator!=(const T_& value_) const { return !(*this == value_); }
175#endif
176
181 template<typename function_t_>
182 hxattr_nodiscard auto and_then(function_t_&& callable_)
184
189 template<typename function_t_>
190 hxattr_nodiscard auto and_then(function_t_&& callable_) const
192
196 template<typename... args_t_>
197 T_& emplace(args_t_&&... args_) noexcept;
198
200 hxattr_nodiscard bool has_value(void) const { return m_engaged_; }
201
205 template<typename function_t_>
206 hxattr_nodiscard hxoptional or_else(function_t_&& callable_) const;
207
210 void reset(void) noexcept;
211
215 void swap(hxoptional& other_) noexcept;
216
220
223 hxattr_nodiscard const T_& value(void) const;
224
228 template<typename U_=T_>
229 hxattr_nodiscard T_ value_or(U_&& default_value_) const;
230
231private:
232 alignas(T_) char m_storage_[sizeof(T_)];
233 bool m_engaged_;
234};
235
239template<typename T_>
243
247template<typename T_, typename... args_t_>
249 hxoptional<T_> result_;
250 result_.emplace(hxforward<args_t_>(args_)...);
251 return result_;
252}
253
257template<typename T_>
259 return opt_.has_value() ? hxkey_hash(*opt_) : hxhash_t{1u};
260}
261
262#include "detail/hxoptional.inl"
263HX_NS_END_
hxoptional<T> - Holds either a value of type T or nothing.
Definition hxoptional.hpp:52
const T & operator*(void) const
Returns a const reference to the contained value.
hxoptional or_else(function_t_ &&callable_) const
Returns a copy of this optional if engaged, otherwise returns the result of calling callable.
hxoptional(const hxoptional< U_ > &other_) noexcept
Constructs by copying the engaged state and converting the value of other to T.
hxoptional & operator=(const hxoptional< U_ > &other_) noexcept
Copies the engaged state and converts the value of other to T.
bool has_value(void) const
Returns true if the optional contains a value.
Definition hxoptional.hpp:200
T value_or(U_ &&default_value_) const
Returns the contained value if engaged, otherwise returns default_value forwarded and converted to T.
T & operator*(void)
Returns a reference to the contained value.
T * operator->(void)
Returns a pointer to the contained value. The optional must be engaged.
hxoptional(void)
Constructs a disengaged hxoptional.
Definition hxoptional.hpp:63
hxoptional & operator=(hxoptional< U_ > &&other_) noexcept
Moves the engaged state and converts the value of other to T.
hxoptional(const hxoptional &other_) noexcept
Copy constructor.
bool operator==(const T &value_) const
Returns true if this optional is engaged and its value equals value.
void reset(void) noexcept
Destroys the contained value if engaged and leaves the optional disengaged.
T & emplace(args_t_ &&... args_) noexcept
Constructs the contained value in place from args, destroying any previous value.
hxoptional(hxoptional< U_ > &&other_) noexcept
Constructs by moving the engaged state and converting the value of other to T.
auto and_then(function_t_ &&callable_) -> hxremove_cvref_t< decltype(hxforward< function_t_ >(callable_)(hxdeclval< T & >()))>
Returns the result of calling callable with the contained value if engaged, otherwise returns a disen...
T value_type
value_type - Publishes the contained value type.
Definition hxoptional.hpp:60
const T * operator->(void) const
Returns a const pointer to the contained value.
hxoptional & operator=(U_ &&value_) noexcept
Assigns value by forwarding, engaging the optional.
T & value(void)
Returns a reference to the contained value.
~hxoptional(void)
Destroys the contained value if engaged.
Definition hxoptional.hpp:98
hxoptional(U_ &&value_) noexcept
Constructs an engaged hxoptional by forwarding value into storage.
bool operator==(const hxoptional &rhs_) const
Returns true if both optionals are disengaged or both are engaged with equal values.
hxoptional & operator=(const hxoptional &other_) noexcept
Copy assignment.
hxoptional & operator=(hxoptional &&other_) noexcept
Move assignment.
auto and_then(function_t_ &&callable_) const -> hxremove_cvref_t< decltype(hxforward< function_t_ >(callable_)(hxdeclval< const T & >()))>
Returns the result of calling callable with the contained value if engaged, otherwise returns a disen...
const T & value(void) const
Returns a const reference to the contained value.
hxoptional & operator=(hxnullopt_t)
Disengages the optional, destroying any contained value.
Definition hxoptional.hpp:129
hxoptional(hxoptional &&other_) noexcept
Move constructor.
hxoptional(hxnullopt_t)
Constructs a disengaged hxoptional from hxnullopt.
Definition hxoptional.hpp:67
void swap(hxoptional &other_) noexcept
Exchanges the contents with other.
bool operator==(hxnullopt_t) const
Returns true if this optional is disengaged.
Definition hxoptional.hpp:156
User-overloadable key-equal, key-less, and key-hash functions.
constexpr hxnullopt_t hxnullopt
hxnullopt - A sentinel value of type hxnullopt_t representing a disengaged hxoptional.
Definition hxoptional.hpp:43
hxhash_t hxkey_hash(const hxoptional< T > &opt_)
hxkey_hash(hxoptional<T>) - Returns the hash of the contained value if engaged, otherwise 1u.
Definition hxoptional.hpp:258
hxoptional< hxremove_cvref_t< T > > hxmake_optional(T &&value_)
hxmake_optional - Returns an engaged hxoptional<hxremove_cvref_t<T>> constructed by forwarding value.
Definition hxoptional.hpp:240
#define hxinline_constexpr
hxinline_constexpr - Enables C++17 compatable "inline constexpr" usage for variables so they can be e...
Definition hxsettings.h:272
#define hxattr_nodiscard
hxattr_nodiscard - Indicates the caller should not discard the return value.
Definition hxsettings.h:89
A few utility functions and most standard C++ meta programming functions.
constexpr T && hxforward(hxremove_reference_t< T > &&x_)
hxforward - Implements std::forward.
Definition hxutility.h:304
hxremove_cv_t< hxremove_reference_t< T > > hxremove_cvref_t
hxremove_cvref_t<T> - Returns T with const, volatile, and references removed.
Definition hxutility.h:115
T && hxdeclval(void) noexcept
hxdeclval - Implements std::declval.
Provides core macros, memory management and feature detection.
uint32_t hxhash_t
hxhash_t - Unsigned 32-bit hash value. Expect collisions.
Definition libhatchet.h:212
static constexpr bool value
Definition hxutility.h:124
hxis_pointer - Returns whether T is a pointer type as hxis_pointer<T>::value.
Definition hxutility.h:206
hxnullopt_t - A tag type used to construct a disengaged hxoptional.
Definition hxoptional.hpp:34
constexpr hxnullopt_t(int)
Explicit constructor prevents implicit construction from { }.
Definition hxoptional.hpp:37