AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
unset.h
1/*
2 * AUI Framework - Declarative UI toolkit for modern C++20
3 * Copyright (C) 2020-2024 Alex2772 and Contributors
4 *
5 * SPDX-License-Identifier: MPL-2.0
6 *
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 */
11
12//
13// Created by alex2 on 03.01.2021.
14//
15
16#pragma once
17
18#include <AUI/Traits/concepts.h>
19#include <AUI/Util/Assert.h>
20#include <algorithm>
21#include <ostream>
22
23#include <fmt/core.h>
24
25namespace ass {
26
27 template<typename T>
28 struct unset_wrap {
29 private:
30 T stored;
31 bool set;
32
33 public:
34 unset_wrap() noexcept:
35 set(false)
36 {
37 }
38
39 template<typename V>
40 unset_wrap(const V& v);
41
42 T& operator*() {
43 AUI_ASSERT(bool(*this));
44 return stored;
45 }
46 const T& operator*() const {
47 AUI_ASSERT(bool(*this));
48 return stored;
49 }
50 T* operator->() {
51 AUI_ASSERT(bool(*this));
52 return &stored;
53 }
54 const T* operator->() const {
55 AUI_ASSERT(bool(*this));
56 return &stored;
57 }
58 T orDefault(const T& def) const {
59 if (set) {
60 return stored;
61 }
62 return def;
63 }
64
65 template<typename Destination>
66 void bindTo(Destination& destination) const {
67 if (set) {
68 destination = stored;
69 }
70 }
71
72 unset_wrap<T>& operator=(const unset_wrap<T>& v) noexcept;
73
74 template<aui::convertible_to<T> U>
75 unset_wrap<T>& operator=(const unset_wrap<U>& v) noexcept;
76
77 bool operator==(const unset_wrap<T>& other) const {
78 if (set != other.set) {
79 return false;
80 }
81 if (set) {
82 return stored == other.stored;
83 }
84 return true;
85 }
86 bool operator!=(const unset_wrap<T>& other) const {
87 return !(*this == other);
88 }
89
90 void reset() noexcept {
91 set = false;
92 }
93
94 operator bool() const {
95 return set;
96 }
97
98 struct unset_wrap_tag {};
99 };
100
101 namespace detail::unset {
102 template<typename T, aui::convertible_to<T> U>
103 void init(unset_wrap<T>& wrap, T& dst, bool& set, const unset_wrap<U>& value) {
104 if (value) {
105 dst = static_cast<T>(*value);
106 set = true;
107 }
108 }
109 template<typename T, aui::convertible_to<T> U>
110 void init(unset_wrap<T>& wrap, T& dst, bool& set, U&& value) {
111 dst = static_cast<T>(std::forward<U>(value));
112 set = true;
113 }
114 }
115
116
117 template<typename T>
118 template<typename V>
119 unset_wrap<T>::unset_wrap(const V& v)
120 {
121 detail::unset::init(*this, stored, set, v);
122 }
123
124 template<typename T>
125 unset_wrap<T>& unset_wrap<T>::operator=(const unset_wrap<T>& v) noexcept {
126 detail::unset::init(*this, stored, set, v);
127 return *this;
128 }
129
130 template<typename T>
131 template<aui::convertible_to<T> U>
132 unset_wrap<T>& unset_wrap<T>::operator=(const unset_wrap<U>& v) noexcept {
133 detail::unset::init(*this, stored, set, v);
134 return *this;
135 }
136
137}
138
139template <typename T> struct fmt::formatter<ass::unset_wrap<T>> {
140 template<typename ParseContext>
141 constexpr auto parse(ParseContext& ctx)
142 {
143 return ctx.begin();
144 }
145
146 auto format(ass::unset_wrap<T> c, format_context& ctx) const {
147 if (c) {
148 return fmt::format_to(ctx.out(), "{}", *c);
149 } else {
150 return fmt::format_to(ctx.out(), "<unset>");
151 }
152 }
153};
154
155template<typename T>
156std::ostream& operator<<(std::ostream& o, const ass::unset_wrap<T>& wrap) {
157 if (wrap) {
158 o << *wrap;
159 } else {
160 o << "<unset>";
161 }
162 return o;
163}
#define AUI_ASSERT(condition)
Asserts that the passed condition evaluates to true.
Definition Assert.h:55
Definition unset.h:98
Definition unset.h:28