123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868 |
- #pragma once
- #include <utility>
- #include "maybe_traits.h"
- #include "yexception.h"
- #include <util/system/align.h>
- #include <util/system/compiler.h>
- #include <util/stream/output.h>
- #include <util/ysaveload.h>
- namespace NMaybe {
- struct TPolicyUndefinedExcept {
- [[noreturn]] static void OnEmpty(const std::type_info& valueTypeInfo);
- };
- struct TPolicyUndefinedFail {
- [[noreturn]] static void OnEmpty(const std::type_info& valueTypeInfo);
- };
- } // namespace NMaybe
- struct [[nodiscard]] TNothing {
- explicit constexpr TNothing(int) noexcept {
- }
- };
- constexpr TNothing NothingObject{0};
- constexpr TNothing Nothing() noexcept {
- return NothingObject;
- }
- constexpr bool operator==(TNothing, TNothing) noexcept {
- return true;
- }
- template <class T, class Policy /*= ::NMaybe::TPolicyUndefinedExcept*/>
- class TMaybe: private TMaybeBase<T> {
- public:
- using TInPlace = NMaybe::TInPlace;
- private:
- static_assert(!std::is_same<std::remove_cv_t<T>, TNothing>::value,
- "Instantiation of TMaybe with a TNothing type is ill-formed");
- static_assert(!std::is_same<std::remove_cv_t<T>, TInPlace>::value,
- "Instantiation of TMaybe with a TInPlace type is ill-formed");
- static_assert(!std::is_reference<T>::value,
- "Instantiation of TMaybe with reference type is ill-formed");
- static_assert(!std::is_array<T>::value,
- "Instantiation of TMaybe with array type is ill-formed");
- static_assert(std::is_destructible<T>::value,
- "Instantiation of TMaybe with non-destructible type is ill-formed");
- template <class U>
- struct TConstructibleFromMaybeSomehow {
- public:
- static constexpr bool value = std::is_constructible<T, TMaybe<U, Policy>&>::value ||
- std::is_constructible<T, const TMaybe<U, Policy>&>::value ||
- std::is_constructible<T, TMaybe<U, Policy>&&>::value ||
- std::is_constructible<T, const TMaybe<U, Policy>&&>::value ||
- std::is_convertible<TMaybe<U, Policy>&, T>::value ||
- std::is_convertible<const TMaybe<U, Policy>&, T>::value ||
- std::is_convertible<TMaybe<U, Policy>&&, T>::value ||
- std::is_convertible<const TMaybe<U, Policy>&&, T>::value;
- };
- template <class U>
- struct TAssignableFromMaybeSomehow {
- public:
- static constexpr bool value = TConstructibleFromMaybeSomehow<U>::value ||
- std::is_assignable<T&, TMaybe<U, Policy>&>::value ||
- std::is_assignable<T&, const TMaybe<U, Policy>&>::value ||
- std::is_assignable<T&, TMaybe<U, Policy>&&>::value ||
- std::is_assignable<T&, const TMaybe<U, Policy>&&>::value;
- };
- template <class U>
- struct TImplicitCopyCtor {
- public:
- static constexpr bool value = std::is_constructible<T, const U&>::value &&
- std::is_convertible<const U&, T>::value &&
- !TConstructibleFromMaybeSomehow<U>::value;
- };
- template <class U>
- struct TExplicitCopyCtor {
- public:
- static constexpr bool value = std::is_constructible<T, const U&>::value &&
- !std::is_convertible<const U&, T>::value &&
- !TConstructibleFromMaybeSomehow<U>::value;
- };
- template <class U>
- struct TImplicitMoveCtor {
- public:
- static constexpr bool value = std::is_constructible<T, U&&>::value &&
- std::is_convertible<U&&, T>::value &&
- !TConstructibleFromMaybeSomehow<U>::value;
- };
- template <class U>
- struct TExplicitMoveCtor {
- public:
- static constexpr bool value = std::is_constructible<T, U&&>::value &&
- !std::is_convertible<U&&, T>::value &&
- !TConstructibleFromMaybeSomehow<U>::value;
- };
- template <class U>
- struct TCopyAssignable {
- public:
- static constexpr bool value = std::is_constructible<T, const U&>::value &&
- std::is_assignable<T&, const U&>::value &&
- !TAssignableFromMaybeSomehow<U>::value;
- };
- template <class U>
- struct TMoveAssignable {
- public:
- static constexpr bool value = std::is_constructible<T, U&&>::value &&
- std::is_assignable<T&, U&&>::value &&
- !TAssignableFromMaybeSomehow<U>::value;
- };
- template <class U>
- struct TImplicitAnyCtor {
- public:
- using UDec = std::decay_t<U>;
- static constexpr bool value = std::is_constructible<T, U>::value &&
- std::is_convertible<U, T>::value &&
- !std::is_same<UDec, TInPlace>::value &&
- !std::is_same<UDec, TMaybe>::value;
- };
- template <class U>
- struct TExplicitAnyCtor {
- public:
- using UDec = std::decay_t<U>;
- static constexpr bool value = std::is_constructible<T, U>::value &&
- !std::is_convertible<U, T>::value &&
- !std::is_same<UDec, TInPlace>::value &&
- !std::is_same<UDec, TMaybe>::value;
- };
- template <class U>
- struct TAssignableFromAny {
- public:
- using UDec = std::decay_t<U>;
- static constexpr bool value = !std::is_same<UDec, TMaybe>::value &&
- std::is_constructible<T, U>::value &&
- std::is_assignable<T&, U>::value &&
- (!std::is_scalar<T>::value || !std::is_same<UDec, T>::value);
- };
- template <typename>
- struct TIsMaybe {
- static constexpr bool value = false;
- };
- template <typename U, typename P>
- struct TIsMaybe<TMaybe<U, P>> {
- static constexpr bool value = true;
- };
- template <typename F, typename... Args>
- static auto Call(F&& f, Args&&... args) -> decltype(std::forward<F>(f)(std::forward<Args>(args)...));
- template <typename F, typename... Args>
- using TCallResult = std::remove_reference_t<std::remove_cv_t<decltype(Call(std::declval<F>(), std::declval<Args>()...))>>;
- template <typename U, typename F>
- static constexpr F&& CheckReturnsMaybe(F&& f) {
- using ReturnType = TCallResult<F, U>;
- static_assert(TIsMaybe<ReturnType>::value, "Function must return TMaybe");
- return f;
- }
- using TBase = TMaybeBase<T>;
- public:
- using value_type = T;
- using TValueType = value_type;
- TMaybe() noexcept = default;
- constexpr TMaybe(const TMaybe&) = default;
- constexpr TMaybe(TMaybe&&) = default;
- template <class... Args>
- constexpr explicit TMaybe(TInPlace, Args&&... args)
- : TBase(TInPlace{}, std::forward<Args>(args)...)
- {
- }
- template <class U, class... TArgs>
- constexpr explicit TMaybe(TInPlace, std::initializer_list<U> il, TArgs&&... args)
- : TBase(TInPlace{}, il, std::forward<TArgs>(args)...)
- {
- }
- constexpr TMaybe(TNothing) noexcept {
- }
- template <class U, class = std::enable_if_t<TImplicitCopyCtor<U>::value>>
- TMaybe(const TMaybe<U, Policy>& right) {
- if (right.Defined()) {
- new (Data()) T(right.GetRef());
- this->Defined_ = true;
- }
- }
- template <class U, std::enable_if_t<TExplicitCopyCtor<U>::value, bool> = false>
- explicit TMaybe(const TMaybe<U, Policy>& right) {
- if (right.Defined()) {
- new (Data()) T(right.GetRef());
- this->Defined_ = true;
- }
- }
- template <class U, class = std::enable_if_t<TImplicitMoveCtor<U>::value>>
- TMaybe(TMaybe<U, Policy>&& right) noexcept(std::is_nothrow_constructible<T, U&&>::value) {
- if (right.Defined()) {
- new (Data()) T(std::move(right.GetRef()));
- this->Defined_ = true;
- }
- }
- template <class U, std::enable_if_t<TExplicitMoveCtor<U>::value, bool> = false>
- explicit TMaybe(TMaybe<U, Policy>&& right) noexcept(std::is_nothrow_constructible<T, U&&>::value) {
- if (right.Defined()) {
- new (Data()) T(std::move(right.GetRef()));
- this->Defined_ = true;
- }
- }
- template <class U = T, class = std::enable_if_t<TImplicitAnyCtor<U>::value>>
- constexpr TMaybe(U&& right)
- : TBase(TInPlace{}, std::forward<U>(right))
- {
- }
- template <class U = T, std::enable_if_t<TExplicitAnyCtor<U>::value, bool> = false>
- constexpr explicit TMaybe(U&& right)
- : TBase(TInPlace{}, std::forward<U>(right))
- {
- }
- ~TMaybe() = default;
- constexpr TMaybe& operator=(const TMaybe&) = default;
- constexpr TMaybe& operator=(TMaybe&&) = default;
- TMaybe& operator=(TNothing) noexcept {
- Clear();
- return *this;
- }
- template <class U = T>
- std::enable_if_t<TAssignableFromAny<U>::value, TMaybe&> operator=(U&& right) {
- if (Defined()) {
- *Data() = std::forward<U>(right);
- } else {
- Init(std::forward<U>(right));
- }
- return *this;
- }
- template <class U>
- std::enable_if_t<TCopyAssignable<U>::value,
- TMaybe&>
- operator=(const TMaybe<U, Policy>& right) {
- if (right.Defined()) {
- if (Defined()) {
- *Data() = right.GetRef();
- } else {
- Init(right.GetRef());
- }
- } else {
- Clear();
- }
- return *this;
- }
- template <class U>
- std::enable_if_t<TMoveAssignable<U>::value,
- TMaybe&>
- operator=(TMaybe<U, Policy>&& right) noexcept(
- std::is_nothrow_assignable<T&, U&&>::value && std::is_nothrow_constructible<T, U&&>::value)
- {
- if (right.Defined()) {
- if (Defined()) {
- *Data() = std::move(right.GetRef());
- } else {
- Init(std::move(right.GetRef()));
- }
- } else {
- Clear();
- }
- return *this;
- }
- template <typename... Args>
- T& ConstructInPlace(Args&&... args) {
- Clear();
- Init(std::forward<Args>(args)...);
- return *Data();
- }
- Y_REINITIALIZES_OBJECT void Clear() noexcept {
- if (Defined()) {
- this->Defined_ = false;
- Data()->~T();
- }
- }
- constexpr bool Defined() const noexcept {
- return this->Defined_;
- }
- Y_PURE_FUNCTION constexpr bool Empty() const noexcept {
- return !Defined();
- }
- void CheckDefined() const {
- if (Y_UNLIKELY(!Defined())) {
- Policy::OnEmpty(typeid(TValueType));
- }
- }
- const T* Get() const noexcept Y_LIFETIME_BOUND {
- return Defined() ? Data() : nullptr;
- }
- T* Get() noexcept Y_LIFETIME_BOUND {
- return Defined() ? Data() : nullptr;
- }
- constexpr const T& GetRef() const& Y_LIFETIME_BOUND {
- CheckDefined();
- return *Data();
- }
- constexpr T& GetRef() & Y_LIFETIME_BOUND {
- CheckDefined();
- return *Data();
- }
- constexpr const T&& GetRef() const&& Y_LIFETIME_BOUND {
- CheckDefined();
- return std::move(*Data());
- }
- constexpr T&& GetRef() && Y_LIFETIME_BOUND {
- CheckDefined();
- return std::move(*Data());
- }
- constexpr const T& operator*() const& Y_LIFETIME_BOUND {
- return GetRef();
- }
- constexpr T& operator*() & Y_LIFETIME_BOUND {
- return GetRef();
- }
- constexpr const T&& operator*() const&& Y_LIFETIME_BOUND {
- return std::move(GetRef());
- }
- constexpr T&& operator*() && Y_LIFETIME_BOUND {
- return std::move(GetRef());
- }
- constexpr const T* operator->() const Y_LIFETIME_BOUND {
- return &GetRef();
- }
- constexpr T* operator->() Y_LIFETIME_BOUND {
- return &GetRef();
- }
- constexpr const T& GetOrElse(const T& elseValue Y_LIFETIME_BOUND) const Y_LIFETIME_BOUND {
- return Defined() ? *Data() : elseValue;
- }
- constexpr T& GetOrElse(T& elseValue Y_LIFETIME_BOUND) Y_LIFETIME_BOUND {
- return Defined() ? *Data() : elseValue;
- }
- constexpr T&& GetOrElse(T&& elseValue Y_LIFETIME_BOUND) && Y_LIFETIME_BOUND {
- return Defined() ? std::move(*Data()) : std::move(elseValue);
- }
- constexpr const TMaybe& OrElse(const TMaybe& elseValue Y_LIFETIME_BOUND) const noexcept Y_LIFETIME_BOUND {
- return Defined() ? *this : elseValue;
- }
- constexpr TMaybe& OrElse(TMaybe& elseValue Y_LIFETIME_BOUND) Y_LIFETIME_BOUND {
- return Defined() ? *this : elseValue;
- }
- constexpr TMaybe&& OrElse(TMaybe&& elseValue Y_LIFETIME_BOUND) && Y_LIFETIME_BOUND {
- return Defined() ? std::move(*this) : std::move(elseValue);
- }
- template <typename F>
- constexpr auto AndThen(F&& func) & {
- using ReturnType = TCallResult<F, T&>;
- if (Defined()) {
- return std::forward<F>(CheckReturnsMaybe<T&>(func))(*Data());
- }
- return ReturnType{};
- }
- template <typename F>
- constexpr auto AndThen(F&& func) const& {
- using ReturnType = TCallResult<F, const T&>;
- if (Defined()) {
- return std::forward<F>(CheckReturnsMaybe<const T&>(func))(*Data());
- }
- return ReturnType{};
- }
- template <typename F>
- constexpr auto AndThen(F&& func) && {
- using ReturnType = TCallResult<F, T&&>;
- if (Defined()) {
- return std::forward<F>(CheckReturnsMaybe<T&&>(func))(std::move(*Data()));
- }
- return ReturnType{};
- }
- template <typename F>
- constexpr auto AndThen(F&& func) const&& {
- using ReturnType = TCallResult<F, const T&&>;
- if (Defined()) {
- return std::forward<F>(CheckReturnsMaybe<const T&&>(func))(std::move(*Data()));
- }
- return ReturnType{};
- }
- template <typename F>
- constexpr auto Transform(F&& func) & {
- using ReturnType = TMaybe<TCallResult<F, T&>>;
- if (Defined()) {
- return ReturnType(std::forward<F>(func)(*Data()));
- }
- return ReturnType{};
- }
- template <typename F>
- constexpr auto Transform(F&& func) const& {
- using ReturnType = TMaybe<TCallResult<F, const T&>>;
- if (Defined()) {
- return ReturnType(std::forward<F>(func)(*Data()));
- }
- return ReturnType{};
- }
- template <typename F>
- constexpr auto Transform(F&& func) && {
- using ReturnType = TMaybe<TCallResult<F, T&&>>;
- if (Defined()) {
- return ReturnType(std::forward<F>(func)(std::move(*Data())));
- }
- return ReturnType{};
- }
- template <typename F>
- constexpr auto Transform(F&& func) const&& {
- using ReturnType = TMaybe<TCallResult<F, const T&&>>;
- if (Defined()) {
- return ReturnType(std::forward<F>(func)(std::move(*Data())));
- }
- return ReturnType{};
- }
- template <typename F>
- constexpr TMaybe Or(F&& func) const& {
- using ResultType = TCallResult<F>;
- static_assert(std::is_same<ResultType, TMaybe>::value, "Function must return TMaybe with the same type");
- if (Defined()) {
- return *this;
- }
- return std::forward<F>(func)();
- }
- template <typename F>
- constexpr TMaybe Or(F&& func) && {
- using ResultType = TCallResult<F>;
- static_assert(std::is_same<ResultType, TMaybe>::value, "Function must return TMaybe with the same type");
- if (Defined()) {
- return std::move(*this);
- }
- return std::forward<F>(func)();
- }
- template <typename U>
- TMaybe<U, Policy> Cast() const {
- return Defined() ? TMaybe<U, Policy>(*Data()) : TMaybe<U, Policy>();
- }
- constexpr explicit operator bool() const noexcept {
- return Defined();
- }
- void Save(IOutputStream* out) const {
- const bool defined = Defined();
- ::Save<bool>(out, defined);
- if (defined) {
- ::Save(out, *Data());
- }
- }
- void Load(IInputStream* in) {
- bool defined;
- ::Load(in, defined);
- if (defined) {
- if (!Defined()) {
- ConstructInPlace();
- }
- ::Load(in, *Data());
- } else {
- Clear();
- }
- }
- void Swap(TMaybe& other) {
- if (this->Defined_ == other.Defined_) {
- if (this->Defined_) {
- ::DoSwap(this->Data_, other.Data_);
- }
- } else {
- if (this->Defined_) {
- other.Init(std::move(this->Data_));
- this->Clear();
- } else {
- this->Init(std::move(other.Data_));
- other.Clear();
- }
- }
- }
- void swap(TMaybe& other) {
- Swap(other);
- }
- private:
- constexpr const T* Data() const noexcept Y_LIFETIME_BOUND {
- return std::addressof(this->Data_);
- }
- constexpr T* Data() noexcept Y_LIFETIME_BOUND {
- return std::addressof(this->Data_);
- }
- template <typename... Args>
- void Init(Args&&... args) {
- new (Data()) T(std::forward<Args>(args)...);
- this->Defined_ = true;
- }
- };
- template <class T>
- using TMaybeFail = TMaybe<T, NMaybe::TPolicyUndefinedFail>;
- template <class T, class TPolicy = ::NMaybe::TPolicyUndefinedExcept>
- constexpr TMaybe<std::decay_t<T>, TPolicy> MakeMaybe(T&& value) {
- return TMaybe<std::decay_t<T>, TPolicy>(std::forward<T>(value));
- }
- template <class T, class... TArgs>
- constexpr TMaybe<T> MakeMaybe(TArgs&&... args) {
- return TMaybe<T>(typename TMaybe<T>::TInPlace{}, std::forward<TArgs>(args)...);
- }
- template <class T, class U, class... TArgs>
- constexpr TMaybe<T> MakeMaybe(std::initializer_list<U> il, TArgs&&... args) {
- return TMaybe<T>(typename TMaybe<T>::TInPlace{}, il, std::forward<TArgs>(args)...);
- }
- template <class T, class TPolicy>
- void Swap(TMaybe<T, TPolicy>& lhs, TMaybe<T, TPolicy>& rhs) {
- lhs.Swap(rhs);
- }
- template <class T, class TPolicy>
- void swap(TMaybe<T, TPolicy>& lhs, TMaybe<T, TPolicy>& rhs) {
- lhs.Swap(rhs);
- }
- template <typename T, class TPolicy>
- struct THash<TMaybe<T, TPolicy>> {
- constexpr size_t operator()(const TMaybe<T, TPolicy>& data) const {
- return (data.Defined()) ? THash<T>()(data.GetRef()) : 42;
- }
- };
- // Comparisons between TMaybe
- template <class T, class TPolicy>
- constexpr bool operator==(const ::TMaybe<T, TPolicy>& left, const ::TMaybe<T, TPolicy>& right) {
- return (static_cast<bool>(left) != static_cast<bool>(right))
- ? false
- : (
- !static_cast<bool>(left)
- ? true
- : *left == *right);
- }
- template <class T, class TPolicy>
- constexpr bool operator!=(const TMaybe<T, TPolicy>& left, const TMaybe<T, TPolicy>& right) {
- return !(left == right);
- }
- template <class T, class TPolicy>
- constexpr bool operator<(const TMaybe<T, TPolicy>& left, const TMaybe<T, TPolicy>& right) {
- return (!static_cast<bool>(right))
- ? false
- : (
- !static_cast<bool>(left)
- ? true
- : (*left < *right));
- }
- template <class T, class TPolicy>
- constexpr bool operator>(const TMaybe<T, TPolicy>& left, const TMaybe<T, TPolicy>& right) {
- return right < left;
- }
- template <class T, class TPolicy>
- constexpr bool operator<=(const TMaybe<T, TPolicy>& left, const TMaybe<T, TPolicy>& right) {
- return !(right < left);
- }
- template <class T, class TPolicy>
- constexpr bool operator>=(const TMaybe<T, TPolicy>& left, const TMaybe<T, TPolicy>& right) {
- return !(left < right);
- }
- // Comparisons with TNothing
- template <class T, class TPolicy>
- constexpr bool operator==(const TMaybe<T, TPolicy>& left, TNothing) noexcept {
- return !static_cast<bool>(left);
- }
- template <class T, class TPolicy>
- constexpr bool operator==(TNothing, const TMaybe<T, TPolicy>& right) noexcept {
- return !static_cast<bool>(right);
- }
- template <class T, class TPolicy>
- constexpr bool operator!=(const TMaybe<T, TPolicy>& left, TNothing) noexcept {
- return static_cast<bool>(left);
- }
- template <class T, class TPolicy>
- constexpr bool operator!=(TNothing, const TMaybe<T, TPolicy>& right) noexcept {
- return static_cast<bool>(right);
- }
- template <class T, class TPolicy>
- constexpr bool operator<(const TMaybe<T, TPolicy>&, TNothing) noexcept {
- return false;
- }
- template <class T, class TPolicy>
- constexpr bool operator<(TNothing, const TMaybe<T, TPolicy>& right) noexcept {
- return static_cast<bool>(right);
- }
- template <class T, class TPolicy>
- constexpr bool operator<=(const TMaybe<T, TPolicy>& left, TNothing) noexcept {
- return !static_cast<bool>(left);
- }
- template <class T, class TPolicy>
- constexpr bool operator<=(TNothing, const TMaybe<T, TPolicy>&) noexcept {
- return true;
- }
- template <class T, class TPolicy>
- constexpr bool operator>(const TMaybe<T, TPolicy>& left, TNothing) noexcept {
- return static_cast<bool>(left);
- }
- template <class T, class TPolicy>
- constexpr bool operator>(TNothing, const TMaybe<T, TPolicy>&) noexcept {
- return false;
- }
- template <class T, class TPolicy>
- constexpr bool operator>=(const TMaybe<T, TPolicy>&, TNothing) noexcept {
- return true;
- }
- template <class T, class TPolicy>
- constexpr bool operator>=(TNothing, const TMaybe<T, TPolicy>& right) noexcept {
- return !static_cast<bool>(right);
- }
- // Comparisons with T
- template <class T, class TPolicy>
- constexpr bool operator==(const TMaybe<T, TPolicy>& maybe, const T& value) {
- return static_cast<bool>(maybe) ? *maybe == value : false;
- }
- template <class T, class TPolicy>
- constexpr bool operator==(const T& value, const TMaybe<T, TPolicy>& maybe) {
- return static_cast<bool>(maybe) ? *maybe == value : false;
- }
- template <class T, class TPolicy>
- constexpr bool operator!=(const TMaybe<T, TPolicy>& maybe, const T& value) {
- return static_cast<bool>(maybe) ? !(*maybe == value) : true;
- }
- template <class T, class TPolicy>
- constexpr bool operator!=(const T& value, const TMaybe<T, TPolicy>& maybe) {
- return static_cast<bool>(maybe) ? !(*maybe == value) : true;
- }
- template <class T, class TPolicy>
- constexpr bool operator<(const TMaybe<T, TPolicy>& maybe, const T& value) {
- return static_cast<bool>(maybe) ? std::less<T>{}(*maybe, value) : true;
- }
- template <class T, class TPolicy>
- constexpr bool operator<(const T& value, const TMaybe<T, TPolicy>& maybe) {
- return static_cast<bool>(maybe) ? std::less<T>{}(value, *maybe) : false;
- }
- template <class T, class TPolicy>
- constexpr bool operator<=(const TMaybe<T, TPolicy>& maybe, const T& value) {
- return !(maybe > value);
- }
- template <class T, class TPolicy>
- constexpr bool operator<=(const T& value, const TMaybe<T, TPolicy>& maybe) {
- return !(value > maybe);
- }
- template <class T, class TPolicy>
- constexpr bool operator>(const TMaybe<T, TPolicy>& maybe, const T& value) {
- return static_cast<bool>(maybe) ? value < maybe : false;
- }
- template <class T, class TPolicy>
- constexpr bool operator>(const T& value, const TMaybe<T, TPolicy>& maybe) {
- return static_cast<bool>(maybe) ? maybe < value : true;
- }
- template <class T, class TPolicy>
- constexpr bool operator>=(const TMaybe<T, TPolicy>& maybe, const T& value) {
- return !(maybe < value);
- }
- template <class T, class TPolicy>
- constexpr bool operator>=(const T& value, const TMaybe<T, TPolicy>& maybe) {
- return !(value < maybe);
- }
- // Comparison with values convertible to T
- template <class T, class TPolicy, class U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
- constexpr bool operator==(const ::TMaybe<T, TPolicy>& maybe, const U& value) {
- return static_cast<bool>(maybe) ? *maybe == value : false;
- }
- template <class T, class TPolicy, class U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
- constexpr bool operator==(const U& value, const ::TMaybe<T, TPolicy>& maybe) {
- return static_cast<bool>(maybe) ? *maybe == value : false;
- }
- template <class T, class TPolicy, class U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
- constexpr bool operator!=(const TMaybe<T, TPolicy>& maybe, const U& value) {
- return static_cast<bool>(maybe) ? !(*maybe == value) : true;
- }
- template <class T, class TPolicy, class U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
- constexpr bool operator!=(const U& value, const TMaybe<T, TPolicy>& maybe) {
- return static_cast<bool>(maybe) ? !(*maybe == value) : true;
- }
- template <class T, class TPolicy, class U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
- constexpr bool operator<(const TMaybe<T, TPolicy>& maybe, const U& value) {
- return static_cast<bool>(maybe) ? std::less<T>{}(*maybe, value) : true;
- }
- template <class T, class TPolicy, class U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
- constexpr bool operator<(const U& value, const TMaybe<T, TPolicy>& maybe) {
- return static_cast<bool>(maybe) ? std::less<T>{}(value, *maybe) : false;
- }
- template <class T, class TPolicy, class U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
- constexpr bool operator<=(const TMaybe<T, TPolicy>& maybe, const U& value) {
- return !(maybe > value);
- }
- template <class T, class TPolicy, class U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
- constexpr bool operator<=(const U& value, const TMaybe<T, TPolicy>& maybe) {
- return !(value > maybe);
- }
- template <class T, class TPolicy, class U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
- constexpr bool operator>(const TMaybe<T, TPolicy>& maybe, const U& value) {
- return static_cast<bool>(maybe) ? value < maybe : false;
- }
- template <class T, class TPolicy, class U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
- constexpr bool operator>(const U& value, const TMaybe<T, TPolicy>& maybe) {
- return static_cast<bool>(maybe) ? maybe < value : true;
- }
- template <class T, class TPolicy, class U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
- constexpr bool operator>=(const TMaybe<T, TPolicy>& maybe, const U& value) {
- return !(maybe < value);
- }
- template <class T, class TPolicy, class U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
- constexpr bool operator>=(const U& value, const TMaybe<T, TPolicy>& maybe) {
- return !(value < maybe);
- }
- class IOutputStream;
- template <class T, class TPolicy>
- inline IOutputStream& operator<<(IOutputStream& out Y_LIFETIME_BOUND, const TMaybe<T, TPolicy>& maybe) {
- if (maybe.Defined()) {
- out << *maybe;
- } else {
- out << TStringBuf("(empty maybe)");
- }
- return out;
- }
|