Loading...
Searching...
No Matches
juce_Optional.h
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
To use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
using Nullopt = std::nullopt_t;
constexpr auto nullopt = std::nullopt;
// Without this, our tests can emit "unreachable code" warnings during
// link time code generation.
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4702)
#ifndef DOXYGEN
#define JUCE_OPTIONAL_OPERATORS X(==) X(!=) X(<) X(<=) X(>) X(>=)
#endif
template <typename Value>
class Optional
{
template <typename> struct IsOptional : std::false_type {};
template <typename T> struct IsOptional<Optional<T>> : std::true_type {};
public:
Optional() = default;
Optional (const Optional&) = default;
Optional (Optional&&) = default;
Optional& operator= (const Optional&) = default;
Optional& operator= (Optional&&) = default;
Optional (Nullopt) noexcept {}
template <typename Head, typename... Tail, std::enable_if_t<! IsOptional<std::decay_t<Head>>::value, int> = 0>
Optional (Head&& head, Tail&&... tail)
noexcept (std::is_nothrow_constructible_v<std::optional<Value>, Head, Tail...>)
: opt (std::forward<Head> (head), std::forward<Tail> (tail)...) {}
template <typename Other>
Optional (const Optional<Other>& other)
noexcept (std::is_nothrow_constructible_v<std::optional<Value>, const std::optional<Other>&>)
: opt (other.opt) {}
template <typename Other>
Optional (Optional<Other>&& other)
noexcept (std::is_nothrow_constructible_v<std::optional<Value>, std::optional<Other>&&>)
: opt (std::move (other.opt)) {}
template <typename Other, std::enable_if_t<! IsOptional<std::decay_t<Other>>::value, int> = 0>
Optional& operator= (Other&& other)
noexcept (std::is_nothrow_assignable_v<std::optional<Value>, Other>)
{
opt = std::forward<Other> (other);
return *this;
}
template <typename Other>
Optional& operator= (const Optional<Other>& other)
noexcept (std::is_nothrow_assignable_v<std::optional<Value>, const std::optional<Other>&>)
{
opt = other.opt;
return *this;
}
template <typename Other>
Optional& operator= (Optional<Other>&& other)
noexcept (std::is_nothrow_assignable_v<std::optional<Value>, std::optional<Other>&&>)
{
opt = std::move (other.opt);
return *this;
}
template <typename... Other>
auto& emplace (Other&&... other)
{
return opt.emplace (std::forward<Other> (other)...);
}
void reset() noexcept
{
opt.reset();
}
void swap (Optional& other)
noexcept (std::is_nothrow_swappable_v<std::optional<Value>>)
{
opt.swap (other.opt);
}
decltype (auto) operator->() { return opt.operator->(); }
decltype (auto) operator->() const { return opt.operator->(); }
decltype (auto) operator* () { return opt.operator* (); }
decltype (auto) operator* () const { return opt.operator* (); }
explicit operator bool() const noexcept { return opt.has_value(); }
bool hasValue() const noexcept { return opt.has_value(); }
template <typename U>
decltype (auto) orFallback (U&& fallback) const& { return opt.value_or (std::forward<U> (fallback)); }
template <typename U>
decltype (auto) orFallback (U&& fallback) & { return opt.value_or (std::forward<U> (fallback)); }
#define X(op) \
template <typename T, typename U> friend bool operator op (const Optional<T>&, const Optional<U>&); \
template <typename T> friend bool operator op (const Optional<T>&, Nullopt); \
template <typename T> friend bool operator op (Nullopt, const Optional<T>&); \
template <typename T, typename U> friend bool operator op (const Optional<T>&, const U&); \
template <typename T, typename U> friend bool operator op (const T&, const Optional<U>&);
JUCE_OPTIONAL_OPERATORS
#undef X
private:
template <typename Other>
friend class Optional;
std::optional<Value> opt;
};
JUCE_END_IGNORE_WARNINGS_MSVC
template <typename Value>
Optional<std::decay_t<Value>> makeOptional (Value&& v)
{
return std::forward<Value> (v);
}
#ifndef DOXYGEN
#define X(op) \
template <typename T, typename U> bool operator op (const Optional<T>& lhs, const Optional<U>& rhs) { return lhs.opt op rhs.opt; } \
template <typename T> bool operator op (const Optional<T>& lhs, Nullopt rhs) { return lhs.opt op rhs; } \
template <typename T> bool operator op (Nullopt lhs, const Optional<T>& rhs) { return lhs op rhs.opt; } \
template <typename T, typename U> bool operator op (const Optional<T>& lhs, const U& rhs) { return lhs.opt op rhs; } \
template <typename T, typename U> bool operator op (const T& lhs, const Optional<U>& rhs) { return lhs op rhs.opt; }
JUCE_OPTIONAL_OPERATORS
#undef X
#undef JUCE_OPTIONAL_OPERATORS
#endif
} // namespace juce
juce::Optional
Definition juce_Optional.h:57
juce::Value
Definition juce_Value.h:51