Iros
 
Loading...
Searching...
No Matches
optional_void.h
Go to the documentation of this file.
1#pragma once
2
6#include "di/meta/language.h"
7#include "di/meta/util.h"
8#include "di/meta/vocab.h"
9#include "di/types/prelude.h"
12
13namespace di::vocab {
14template<>
15class Optional<void> : public function::monad::MonadInterface<Optional<void>> {
16public:
17 using Value = void;
18
19 constexpr Optional() = default;
20 constexpr Optional(NullOpt) {}
21
22 constexpr Optional(Optional const&) = default;
23 constexpr Optional(Optional&&) = default;
24
25 constexpr explicit Optional(InPlace) : m_has_value(true) {}
26 constexpr explicit Optional(bool value) : m_has_value(value) {}
27
28 constexpr ~Optional() = default;
29
30 constexpr auto operator=(Optional const&) -> Optional& = default;
31 constexpr auto operator=(Optional&&) -> Optional& = default;
32
33 constexpr auto operator=(NullOpt) -> Optional& {
34 m_has_value = false;
35 return *this;
36 }
37
38 constexpr auto operator=(bool value) -> Optional& {
39 m_has_value = value;
40 return *this;
41 }
42
43 constexpr auto has_value() const -> bool { return m_has_value; }
44 constexpr explicit operator bool() const { return has_value(); }
45
46 constexpr void operator*() const { DI_ASSERT(has_value()); }
47
48 constexpr void value() const& { DI_ASSERT(has_value()); }
49 constexpr void value() && { DI_ASSERT(has_value()); }
50
51 constexpr void reset() { m_has_value = false; }
52
53 constexpr void emplace() { m_has_value = true; }
54
55private:
56 constexpr friend auto operator==(Optional const& a, Optional const& b) -> bool {
57 return a.has_value() == b.has_value();
58 }
59 constexpr friend auto operator==(Optional const& a, bool b) -> bool { return bool(a) == b; }
60 constexpr friend auto operator==(Optional const& a, NullOpt) -> bool { return !a.has_value(); }
61
62 constexpr friend auto operator<=>(Optional const& a, Optional const& b) -> strong_ordering {
63 return a.has_value() <=> b.has_value();
64 }
65 constexpr friend auto operator<=>(Optional const& a, bool b) -> strong_ordering { return bool(a) <=> b; }
66 constexpr friend auto operator<=>(Optional const& a, NullOpt) -> strong_ordering { return bool(a) <=> false; }
67
68 template<concepts::DecaySameAs<Optional> Self, typename F, typename R = meta::InvokeResult<F>>
69 requires(concepts::Optional<R>)
70 constexpr friend auto tag_invoke(types::Tag<function::monad::bind>, Self&& self, F&& f) -> R {
71 if (self.has_value()) {
72 return function::invoke(util::forward<F>(f));
73 }
74 return R();
75 }
76
77 template<concepts::DecaySameAs<Optional> Self, typename F, typename U = meta::UnwrapRefDecay<meta::InvokeResult<F>>>
78 constexpr friend auto tag_invoke(types::Tag<function::monad::fmap>, Self&& self, F&& f) -> Optional<U> {
79 if (self.has_value()) {
80 if constexpr (concepts::LanguageVoid<U>) {
81 function::invoke(util::forward<F>(f));
83 } else {
84 return Optional<U>(types::in_place, function::invoke(util::forward<F>(f)));
85 }
86 } else {
87 return nullopt;
88 }
89 }
90
91 template<concepts::DecaySameAs<Optional> Self, concepts::InvocableTo<Optional> F>
92 constexpr friend auto tag_invoke(types::Tag<function::monad::fail>, Self&& self, F&& f) -> Optional {
93 return self.has_value() ? util::forward<Self>(self) : function::invoke(util::forward<F>(f));
94 }
95
96 bool m_has_value { false };
97};
98}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition monad_interface.h:15
constexpr Optional(InPlace)
Definition optional_void.h:25
constexpr friend auto operator<=>(Optional const &a, NullOpt) -> strong_ordering
Definition optional_void.h:66
constexpr friend auto operator==(Optional const &a, NullOpt) -> bool
Definition optional_void.h:60
constexpr friend auto tag_invoke(types::Tag< function::monad::fail >, Self &&self, F &&f) -> Optional
Definition optional_void.h:92
constexpr friend auto operator<=>(Optional const &a, Optional const &b) -> strong_ordering
Definition optional_void.h:62
constexpr void emplace()
Definition optional_void.h:53
constexpr auto has_value() const -> bool
Definition optional_void.h:43
constexpr void reset()
Definition optional_void.h:51
constexpr friend auto tag_invoke(types::Tag< function::monad::bind >, Self &&self, F &&f) -> R
Definition optional_void.h:70
constexpr friend auto operator<=>(Optional const &a, bool b) -> strong_ordering
Definition optional_void.h:65
constexpr auto operator=(bool value) -> Optional &
Definition optional_void.h:38
constexpr friend auto tag_invoke(types::Tag< function::monad::fmap >, Self &&self, F &&f) -> Optional< U >
Definition optional_void.h:78
constexpr friend auto operator==(Optional const &a, bool b) -> bool
Definition optional_void.h:59
constexpr friend auto operator==(Optional const &a, Optional const &b) -> bool
Definition optional_void.h:56
constexpr Optional(bool value)
Definition optional_void.h:26
constexpr Optional(Optional const &)=default
constexpr Optional(Optional &&)=default
constexpr auto operator=(Optional &&) -> Optional &=default
constexpr void operator*() const
Definition optional_void.h:46
void Value
Definition optional_void.h:17
constexpr auto operator=(Optional const &) -> Optional &=default
constexpr ~Optional()=default
constexpr void value() const &
Definition optional_void.h:48
constexpr Optional()=default
constexpr Optional(NullOpt)
Definition optional_void.h:20
constexpr auto operator=(NullOpt) -> Optional &
Definition optional_void.h:33
constexpr void value() &&
Definition optional_void.h:49
Definition core.h:128
Definition vocab.h:77
constexpr auto invoke
Definition invoke.h:100
constexpr auto in_place
Definition in_place.h:8
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
Definition lazy.h:165
Optional(T) -> Optional< T >
constexpr auto nullopt
Definition nullopt.h:15
Definition in_place.h:4
Definition nullopt.h:6