OpenShot Audio Library | OpenShotAudio  0.6.0
juce_Optional.h
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2022 - Raw Material Software Limited
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 using Nullopt = std::nullopt_t;
27 constexpr auto nullopt = std::nullopt;
28 
29 // Without this, our tests can emit "unreachable code" warnings during
30 // link time code generation.
31 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4702)
32 
33 #ifndef DOXYGEN
34 #define JUCE_OPTIONAL_OPERATORS X(==) X(!=) X(<) X(<=) X(>) X(>=)
35 #endif
36 
55 template <typename Value>
56 class Optional
57 {
58  template <typename> struct IsOptional : std::false_type {};
59  template <typename T> struct IsOptional<Optional<T>> : std::true_type {};
60 
61 public:
62  Optional() = default;
63  Optional (const Optional&) = default;
64  Optional (Optional&&) = default;
65  Optional& operator= (const Optional&) = default;
66  Optional& operator= (Optional&&) = default;
67 
68  Optional (Nullopt) noexcept {}
69 
70  template <typename Head, typename... Tail, std::enable_if_t<! IsOptional<std::decay_t<Head>>::value, int> = 0>
71  Optional (Head&& head, Tail&&... tail)
72  noexcept (std::is_nothrow_constructible_v<std::optional<Value>, Head, Tail...>)
73  : opt (std::forward<Head> (head), std::forward<Tail> (tail)...) {}
74 
75  template <typename Other>
76  Optional (const Optional<Other>& other)
77  noexcept (std::is_nothrow_constructible_v<std::optional<Value>, const std::optional<Other>&>)
78  : opt (other.opt) {}
79 
80  template <typename Other>
81  Optional (Optional<Other>&& other)
82  noexcept (std::is_nothrow_constructible_v<std::optional<Value>, std::optional<Other>&&>)
83  : opt (std::move (other.opt)) {}
84 
85  template <typename Other, std::enable_if_t<! IsOptional<std::decay_t<Other>>::value, int> = 0>
86  Optional& operator= (Other&& other)
87  noexcept (std::is_nothrow_assignable_v<std::optional<Value>, Other>)
88  {
89  opt = std::forward<Other> (other);
90  return *this;
91  }
92 
93  template <typename Other>
94  Optional& operator= (const Optional<Other>& other)
95  noexcept (std::is_nothrow_assignable_v<std::optional<Value>, const std::optional<Other>&>)
96  {
97  opt = other.opt;
98  return *this;
99  }
100 
101  template <typename Other>
102  Optional& operator= (Optional<Other>&& other)
103  noexcept (std::is_nothrow_assignable_v<std::optional<Value>, std::optional<Other>&&>)
104  {
105  opt = std::move (other.opt);
106  return *this;
107  }
108 
109  template <typename... Other>
110  auto& emplace (Other&&... other)
111  {
112  return opt.emplace (std::forward<Other> (other)...);
113  }
114 
115  void reset() noexcept
116  {
117  opt.reset();
118  }
119 
120  void swap (Optional& other)
121  noexcept (std::is_nothrow_swappable_v<std::optional<Value>>)
122  {
123  opt.swap (other.opt);
124  }
125 
126  decltype (auto) operator->() { return opt.operator->(); }
127  decltype (auto) operator->() const { return opt.operator->(); }
128  decltype (auto) operator* () { return opt.operator* (); }
129  decltype (auto) operator* () const { return opt.operator* (); }
130 
131  explicit operator bool() const noexcept { return opt.has_value(); }
132  bool hasValue() const noexcept { return opt.has_value(); }
133 
134  template <typename U>
135  decltype (auto) orFallback (U&& fallback) const& { return opt.value_or (std::forward<U> (fallback)); }
136 
137  template <typename U>
138  decltype (auto) orFallback (U&& fallback) & { return opt.value_or (std::forward<U> (fallback)); }
139 
140  #define X(op) \
141  template <typename T, typename U> friend bool operator op (const Optional<T>&, const Optional<U>&); \
142  template <typename T> friend bool operator op (const Optional<T>&, Nullopt); \
143  template <typename T> friend bool operator op (Nullopt, const Optional<T>&); \
144  template <typename T, typename U> friend bool operator op (const Optional<T>&, const U&); \
145  template <typename T, typename U> friend bool operator op (const T&, const Optional<U>&);
146 
147  JUCE_OPTIONAL_OPERATORS
148 
149  #undef X
150 
151 private:
152  template <typename Other>
153  friend class Optional;
154 
155  std::optional<Value> opt;
156 };
157 
158 JUCE_END_IGNORE_WARNINGS_MSVC
159 
160 template <typename Value>
161 Optional<std::decay_t<Value>> makeOptional (Value&& v)
162 {
163  return std::forward<Value> (v);
164 }
165 
166 #ifndef DOXYGEN
167 #define X(op) \
168  template <typename T, typename U> bool operator op (const Optional<T>& lhs, const Optional<U>& rhs) { return lhs.opt op rhs.opt; } \
169  template <typename T> bool operator op (const Optional<T>& lhs, Nullopt rhs) { return lhs.opt op rhs; } \
170  template <typename T> bool operator op (Nullopt lhs, const Optional<T>& rhs) { return lhs op rhs.opt; } \
171  template <typename T, typename U> bool operator op (const Optional<T>& lhs, const U& rhs) { return lhs.opt op rhs; } \
172  template <typename T, typename U> bool operator op (const T& lhs, const Optional<U>& rhs) { return lhs op rhs.opt; }
173 
174 JUCE_OPTIONAL_OPERATORS
175 
176 #undef X
177 #undef JUCE_OPTIONAL_OPERATORS
178 #endif
179 
180 } // namespace juce