2 #include <ossia/detail/config.hpp>
4 #include <ossia/detail/variant.hpp>
6 #include <boost/mp11.hpp>
11 struct nullable_variant_index
14 OSSIA_MAXIMUM_INLINE constexpr
bool valid() const noexcept {
return value != 0; }
15 OSSIA_MAXIMUM_INLINE constexpr std::size_t index() const noexcept {
return value; }
16 OSSIA_MAXIMUM_INLINE constexpr std::size_t to_std_index() const noexcept
21 OSSIA_MAXIMUM_INLINE constexpr
bool
22 operator==(nullable_variant_index lhs, nullable_variant_index rhs) noexcept
24 return lhs.value == rhs.value;
26 OSSIA_MAXIMUM_INLINE constexpr
bool
27 operator!=(nullable_variant_index lhs, nullable_variant_index rhs) noexcept
29 return lhs.value != rhs.value;
31 OSSIA_MAXIMUM_INLINE constexpr
bool
32 operator<(nullable_variant_index lhs, nullable_variant_index rhs) noexcept
34 return lhs.value < rhs.value;
37 template <
typename... Args>
38 struct nullable_variant
39 :
public ossia_variant_alias::variant<ossia_variant_alias::monostate, Args...>
42 typename ossia_variant_alias::variant<ossia_variant_alias::monostate, Args...>;
45 static constexpr nullable_variant_index npos{0};
48 static constexpr nullable_variant_index index_of() noexcept
50 if constexpr(!boost::mp11::mp_contains<base, T>::value)
53 return {boost::mp11::mp_find<base, T>::value};
56 OSSIA_MAXIMUM_INLINE constexpr
operator bool() const noexcept
58 return this->index() != 0;
61 OSSIA_MAXIMUM_INLINE constexpr nullable_variant_index which() const noexcept
63 return nullable_variant_index{this->index()};
67 OSSIA_MAXIMUM_INLINE constexpr T* target() noexcept
69 return ossia_variant_alias::get_if<T>(
this);
72 OSSIA_MAXIMUM_INLINE constexpr
const T* target() const noexcept
74 return ossia_variant_alias::get_if<T>(
this);
78 OSSIA_MAXIMUM_INLINE constexpr
void* target() noexcept {
return this; }
80 OSSIA_MAXIMUM_INLINE constexpr
const void* target() const noexcept {
return this; }
91 template <
typename F,
typename... Args>
92 OSSIA_MAXIMUM_INLINE
auto apply(F&& visitor, ossia::nullable_variant<Args...>& variant)
95 return ossia_variant_alias::visit(visitor, variant);
97 template <
typename F,
typename... Args>
98 OSSIA_MAXIMUM_INLINE
auto
99 apply(F&& visitor,
const ossia::nullable_variant<Args...>& variant) -> decltype(
auto)
101 return ossia_variant_alias::visit(visitor, variant);
103 template <
typename F,
typename... Args>
104 OSSIA_MAXIMUM_INLINE
auto apply(F&& visitor, ossia::nullable_variant<Args...>&& variant)
107 return ossia_variant_alias::visit(visitor, std::move(variant));
110 template <
typename F,
typename... Args>
111 OSSIA_MAXIMUM_INLINE
auto
112 apply_nonnull(F&& visitor, ossia::nullable_variant<Args...>& variant) -> decltype(
auto)
116 return ossia_variant_alias::visit(visitor, variant);
120 ossia_do_throw(std::runtime_error,
"apply_nonnull called on invalid variant");
123 template <
typename F,
typename... Args>
124 OSSIA_MAXIMUM_INLINE
auto
125 apply_nonnull(F&& visitor,
const ossia::nullable_variant<Args...>& variant)
130 return ossia_variant_alias::visit(visitor, variant);
134 ossia_do_throw(std::runtime_error,
"apply_nonnull called on invalid variant");
137 template <
typename F,
typename... Args>
138 OSSIA_MAXIMUM_INLINE
auto
139 apply_nonnull(F&& visitor, ossia::nullable_variant<Args...>&& variant) -> decltype(
auto)
143 return ossia_variant_alias::visit(visitor, std::move(variant));
147 ossia_do_throw(std::runtime_error,
"apply_nonnull called on invalid variant");
150 template <
typename F,
typename... Args>
151 OSSIA_MAXIMUM_INLINE
auto apply_nonnull(
152 F&& visitor, ossia::nullable_variant<Args...>& v1,
153 ossia::nullable_variant<Args...>& v2) -> decltype(
auto)
157 return ossia_variant_alias::visit(visitor, v1, v2);
161 ossia_do_throw(std::runtime_error,
"apply_nonnull called on invalid variant");
164 template <
typename F,
typename... Args>
165 OSSIA_MAXIMUM_INLINE
auto apply_nonnull(
166 F&& visitor,
const ossia::nullable_variant<Args...>& v1,
167 const ossia::nullable_variant<Args...>& v2) -> decltype(
auto)
171 return ossia_variant_alias::visit(visitor, v1, v2);
175 ossia_do_throw(std::runtime_error,
"apply_nonnull called on invalid variant");
178 template <
typename F,
typename... Args>
179 OSSIA_MAXIMUM_INLINE
auto apply_nonnull(
180 F&& visitor, ossia::nullable_variant<Args...>&& v1,
181 const ossia::nullable_variant<Args...>&& v2) -> decltype(
auto)
185 return ossia_variant_alias::visit(visitor, std::move(v1), std::move(v2));
189 ossia_do_throw(std::runtime_error,
"apply_nonnull called on invalid variant");
193 template <
typename... Ts>
194 OSSIA_MAXIMUM_INLINE constexpr
bool
195 operator==(
const nullable_variant<Ts...>& lhs,
const nullable_variant<Ts...>& rhs)
197 return ((
const typename nullable_variant<Ts...>::base&)lhs)
198 == ((
const typename nullable_variant<Ts...>::base&)rhs);
200 template <
typename... Ts>
201 OSSIA_MAXIMUM_INLINE constexpr
bool
202 operator!=(
const nullable_variant<Ts...>& lhs,
const nullable_variant<Ts...>& rhs)
204 return ((
const typename nullable_variant<Ts...>::base&)lhs)
205 != ((
const typename nullable_variant<Ts...>::base&)rhs);
207 template <
typename... Ts>
208 OSSIA_MAXIMUM_INLINE constexpr
bool
209 operator<(
const nullable_variant<Ts...>& lhs,
const nullable_variant<Ts...>& rhs)
211 return ((
const typename nullable_variant<Ts...>::base&)lhs)
212 < ((
const typename nullable_variant<Ts...>::base&)rhs);
214 template <
typename... Ts>
215 OSSIA_MAXIMUM_INLINE constexpr
bool
216 operator>(
const nullable_variant<Ts...>& lhs,
const nullable_variant<Ts...>& rhs)
218 return ((
const typename nullable_variant<Ts...>::base&)lhs)
219 > ((
const typename nullable_variant<Ts...>::base&)rhs);
221 template <
typename... Ts>
222 OSSIA_MAXIMUM_INLINE constexpr
bool
223 operator<=(
const nullable_variant<Ts...>& lhs,
const nullable_variant<Ts...>& rhs)
225 return ((
const typename nullable_variant<Ts...>::base&)lhs)
226 <= ((
const typename nullable_variant<Ts...>::base&)rhs);
228 template <
typename... Ts>
229 OSSIA_MAXIMUM_INLINE constexpr
bool
230 operator>=(
const nullable_variant<Ts...>& lhs,
const nullable_variant<Ts...>& rhs)
232 return ((
const typename nullable_variant<Ts...>::base&)lhs)
233 >= ((
const typename nullable_variant<Ts...>::base&)rhs);
236 template <
typename L,
typename... Ts>
237 OSSIA_MAXIMUM_INLINE constexpr
bool
238 operator==(
const L& lhs,
const nullable_variant<Ts...>& rhs)
240 constexpr
auto lhs_idx = nullable_variant<Ts...>::template index_of<L>();
241 static_assert(lhs_idx != nullable_variant<Ts...>::npos);
243 if(lhs_idx != rhs.which())
246 return lhs == *rhs.template target<L>();
249 template <
typename L,
typename... Ts>
250 OSSIA_MAXIMUM_INLINE constexpr
bool
251 operator!=(
const L& lhs,
const nullable_variant<Ts...>& rhs)
253 constexpr
auto lhs_idx = nullable_variant<Ts...>::template index_of<L>();
254 static_assert(lhs_idx != nullable_variant<Ts...>::npos);
256 if(lhs_idx != rhs.which())
259 return lhs != *rhs.template target<L>();
263 template <
typename L,
typename... Ts>
264 OSSIA_MAXIMUM_INLINE constexpr
bool
265 operator<(
const L& lhs,
const nullable_variant<Ts...>& rhs)
267 constexpr
auto lhs_idx = nullable_variant<Ts...>::template index_of<L>();
268 static_assert(lhs_idx != nullable_variant<Ts...>::npos);
270 if(lhs_idx < rhs.which())
272 else if(lhs_idx > rhs.which())
275 return lhs < *rhs.template target<L>();
279 template <
typename L,
typename... Ts>
280 OSSIA_MAXIMUM_INLINE constexpr
bool
281 operator>(
const L& lhs,
const nullable_variant<Ts...>& rhs)
283 constexpr
auto lhs_idx = nullable_variant<Ts...>::template index_of<L>();
284 static_assert(lhs_idx != nullable_variant<Ts...>::npos);
286 if(lhs_idx > rhs.which())
288 else if(lhs_idx < rhs.which())
291 return lhs > *rhs.template target<L>();
294 template <
typename L,
typename... Ts>
295 OSSIA_MAXIMUM_INLINE constexpr
bool
296 operator<=(
const L& lhs,
const nullable_variant<Ts...>& rhs)
298 constexpr
auto lhs_idx = nullable_variant<Ts...>::template index_of<L>();
299 static_assert(lhs_idx != nullable_variant<Ts...>::npos);
301 if(lhs_idx < rhs.which())
303 else if(lhs_idx > rhs.which())
306 return lhs <= *rhs.template target<L>();
309 template <
typename L,
typename... Ts>
310 OSSIA_MAXIMUM_INLINE constexpr
bool
311 operator>=(
const L& lhs,
const nullable_variant<Ts...>& rhs)
313 constexpr
auto lhs_idx = nullable_variant<Ts...>::template index_of<L>();
314 static_assert(lhs_idx != nullable_variant<Ts...>::npos);
316 if(lhs_idx > rhs.which())
318 else if(lhs_idx < rhs.which())
321 return lhs >= *rhs.template target<L>();
324 template <
typename R,
typename... Ts>
325 OSSIA_MAXIMUM_INLINE constexpr
bool
326 operator==(
const nullable_variant<Ts...>& lhs,
const R& rhs)
328 constexpr
auto rhs_idx = nullable_variant<Ts...>::template index_of<R>();
329 static_assert(rhs_idx != nullable_variant<Ts...>::npos);
331 if(lhs.which() != rhs_idx)
334 return *lhs.template target<R>() == rhs;
338 template <
typename R,
typename... Ts>
339 OSSIA_MAXIMUM_INLINE constexpr
bool
340 operator!=(
const nullable_variant<Ts...>& lhs,
const R& rhs)
342 constexpr
auto rhs_idx = nullable_variant<Ts...>::template index_of<R>();
343 static_assert(rhs_idx != nullable_variant<Ts...>::npos);
345 if(lhs.which() != rhs_idx)
348 return *lhs.template target<R>() != rhs;
352 template <
typename R,
typename... Ts>
353 OSSIA_MAXIMUM_INLINE constexpr
bool
354 operator<(
const nullable_variant<Ts...>& lhs,
const R& rhs)
356 constexpr
auto rhs_idx = nullable_variant<Ts...>::template index_of<R>();
357 static_assert(rhs_idx != nullable_variant<Ts...>::npos);
359 if(lhs.which() < rhs_idx)
361 else if(lhs.which() > rhs_idx)
364 return *lhs.template target<R>() < rhs;
367 template <
typename R,
typename... Ts>
368 OSSIA_MAXIMUM_INLINE constexpr
bool
369 operator>(
const nullable_variant<Ts...>& lhs,
const R& rhs)
371 constexpr
auto rhs_idx = nullable_variant<Ts...>::template index_of<R>();
372 static_assert(rhs_idx != nullable_variant<Ts...>::npos);
374 if(lhs.which() > rhs_idx)
376 else if(lhs.which() < rhs_idx)
379 return *lhs.template target<R>() > rhs;
382 template <
typename R,
typename... Ts>
383 OSSIA_MAXIMUM_INLINE constexpr
bool
384 operator<=(
const nullable_variant<Ts...>& lhs,
const R& rhs)
386 constexpr
auto rhs_idx = nullable_variant<Ts...>::template index_of<R>();
387 static_assert(rhs_idx != nullable_variant<Ts...>::npos);
389 if(lhs.which() < rhs_idx)
391 else if(lhs.which() > rhs_idx)
394 return *lhs.template target<R>() <= rhs;
397 template <
typename R,
typename... Ts>
398 OSSIA_MAXIMUM_INLINE constexpr
bool
399 operator>=(
const nullable_variant<Ts...>& lhs,
const R& rhs)
401 constexpr
auto rhs_idx = nullable_variant<Ts...>::template index_of<R>();
402 static_assert(rhs_idx != nullable_variant<Ts...>::npos);
404 if(lhs.which() > rhs_idx)
406 else if(lhs.which() < rhs_idx)
409 return *lhs.template target<R>() >= rhs;