2015-06-28 20:28:29 +00:00
|
|
|
/* Option type implementation. Inspired by libc++.
|
|
|
|
*
|
|
|
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
|
|
*/
|
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#ifndef OSTD_MAYBE_HH
|
|
|
|
#define OSTD_MAYBE_HH
|
2015-06-28 20:28:29 +00:00
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#include "ostd/types.hh"
|
|
|
|
#include "ostd/type_traits.hh"
|
|
|
|
#include "ostd/memory.hh"
|
|
|
|
#include "ostd/utility.hh"
|
|
|
|
#include "ostd/initializer_list.hh"
|
|
|
|
#include "ostd/functional.hh"
|
2015-06-28 20:28:29 +00:00
|
|
|
|
2015-07-13 19:07:14 +00:00
|
|
|
namespace ostd {
|
2015-06-28 20:28:29 +00:00
|
|
|
|
|
|
|
struct InPlace {};
|
|
|
|
constexpr InPlace in_place = InPlace();
|
|
|
|
|
|
|
|
struct Nothing {
|
|
|
|
explicit constexpr Nothing(int) {}
|
|
|
|
};
|
|
|
|
constexpr Nothing nothing = Nothing(0);
|
|
|
|
|
|
|
|
namespace detail {
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, bool = IsTriviallyDestructible<T>::value>
|
2015-06-28 20:28:29 +00:00
|
|
|
class MaybeStorage {
|
|
|
|
protected:
|
|
|
|
using Value = T;
|
|
|
|
union {
|
|
|
|
char p_null_state;
|
|
|
|
Value p_value;
|
|
|
|
};
|
|
|
|
bool p_engaged = false;
|
|
|
|
|
|
|
|
constexpr MaybeStorage(): p_null_state('\0') {}
|
|
|
|
|
|
|
|
MaybeStorage(const MaybeStorage &v): p_engaged(v.p_engaged) {
|
2015-07-05 22:59:36 +00:00
|
|
|
if (p_engaged) ::new(address_of(p_value)) Value(v.p_value);
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MaybeStorage(MaybeStorage &&v): p_engaged(v.p_engaged) {
|
|
|
|
if (p_engaged)
|
2015-07-05 22:59:36 +00:00
|
|
|
::new(address_of(p_value)) Value(move(v.p_value));
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
constexpr MaybeStorage(const Value &v): p_value(v), p_engaged(true) {}
|
2015-07-05 22:59:36 +00:00
|
|
|
constexpr MaybeStorage(Value &&v): p_value(move(v)), p_engaged(true) {}
|
2015-06-28 20:28:29 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename ...A> constexpr MaybeStorage(InPlace, A &&...args):
|
|
|
|
p_value(forward<A>(args)...), p_engaged(true) {}
|
2015-06-28 20:28:29 +00:00
|
|
|
|
|
|
|
~MaybeStorage() {
|
|
|
|
if (p_engaged) p_value.~Value();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class MaybeStorage<T, true> {
|
|
|
|
protected:
|
|
|
|
using Value = T;
|
|
|
|
union {
|
|
|
|
char p_null_state;
|
|
|
|
Value p_value;
|
|
|
|
};
|
|
|
|
bool p_engaged = false;
|
|
|
|
|
|
|
|
constexpr MaybeStorage(): p_null_state('\0') {}
|
|
|
|
|
|
|
|
MaybeStorage(const MaybeStorage &v): p_engaged(v.p_engaged) {
|
2015-07-05 22:59:36 +00:00
|
|
|
if (p_engaged) ::new(address_of(p_value)) Value(v.p_value);
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MaybeStorage(MaybeStorage &&v): p_engaged(v.p_engaged) {
|
|
|
|
if (p_engaged)
|
2015-07-05 22:59:36 +00:00
|
|
|
::new(address_of(p_value)) Value(move(v.p_value));
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
constexpr MaybeStorage(const Value &v): p_value(v), p_engaged(true) {}
|
|
|
|
constexpr MaybeStorage(Value &&v):
|
2015-07-05 22:59:36 +00:00
|
|
|
p_value(move(v)), p_engaged(true) {}
|
2015-06-28 20:28:29 +00:00
|
|
|
|
|
|
|
template<typename ...A>
|
2015-07-05 22:59:36 +00:00
|
|
|
constexpr MaybeStorage(InPlace, A &&...args):
|
|
|
|
p_value(forward<A>(args)...), p_engaged(true) {}
|
2015-06-28 20:28:29 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
class Maybe: private detail::MaybeStorage<T> {
|
|
|
|
using Base = detail::MaybeStorage<T>;
|
2015-06-28 20:28:29 +00:00
|
|
|
public:
|
|
|
|
using Value = T;
|
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
static_assert(!IsReference<T>::value,
|
2015-06-28 20:28:29 +00:00
|
|
|
"Initialization of Maybe with a reference type is not allowed.");
|
2015-07-05 22:59:36 +00:00
|
|
|
static_assert(!IsSame<RemoveCv<T>, InPlace>::value,
|
2015-06-28 20:28:29 +00:00
|
|
|
"Initialization of Maybe with InPlace is not allowed.");
|
2015-07-05 22:59:36 +00:00
|
|
|
static_assert(!IsSame<RemoveCv<T>, Nothing>::value,
|
2015-06-28 20:28:29 +00:00
|
|
|
"Initialization of Maybe with Nothing is not allowed.");
|
2015-07-05 22:59:36 +00:00
|
|
|
static_assert(IsObject<T>::value,
|
2015-06-28 20:28:29 +00:00
|
|
|
"Initialization of Maybe with non-object type is not allowed.");
|
2015-07-05 22:59:36 +00:00
|
|
|
static_assert(IsDestructible<T>::value,
|
2015-06-28 20:28:29 +00:00
|
|
|
"Initialization of Maybe with a non-destructible object is not allowed.");
|
|
|
|
|
|
|
|
constexpr Maybe() {}
|
|
|
|
Maybe(const Maybe &) = default;
|
|
|
|
Maybe(Maybe &&) = default;
|
2015-07-05 22:59:36 +00:00
|
|
|
constexpr Maybe(Nothing) {}
|
2015-06-28 20:28:29 +00:00
|
|
|
constexpr Maybe(const Value &v): Base(v) {}
|
2015-07-05 22:59:36 +00:00
|
|
|
constexpr Maybe(Value &&v): Base(move(v)) {}
|
2015-06-28 20:28:29 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename ...A, typename = EnableIf<
|
|
|
|
IsConstructible<T, A...>::value>>
|
|
|
|
constexpr explicit Maybe(InPlace, A &&...args): Base(in_place,
|
|
|
|
forward<A>(args)...) {}
|
2015-06-28 20:28:29 +00:00
|
|
|
|
2015-07-15 21:03:51 +00:00
|
|
|
template<typename U, typename ...A, typename = EnableIf<
|
2015-07-05 22:59:36 +00:00
|
|
|
IsConstructible<T, std::initializer_list<U> &, A...>::value>>
|
2015-06-28 20:28:29 +00:00
|
|
|
constexpr explicit
|
2015-07-05 22:59:36 +00:00
|
|
|
Maybe(InPlace, std::initializer_list<U> il, A &&...args):
|
|
|
|
Base(in_place, il, forward<A>(args)...) {}
|
2015-06-28 20:28:29 +00:00
|
|
|
|
|
|
|
~Maybe() = default;
|
|
|
|
|
|
|
|
Maybe &operator=(Nothing) {
|
|
|
|
if (this->p_engaged) {
|
|
|
|
this->p_value.~Value();
|
|
|
|
this->p_engaged = false;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Maybe &operator=(const Maybe &v) {
|
|
|
|
if (this->p_engaged == v.p_engaged) {
|
|
|
|
if (this->p_engaged) this->p_value = v.p_value;
|
|
|
|
} else {
|
|
|
|
if (this->p_engaged)
|
|
|
|
this->p_value.~Value();
|
|
|
|
else
|
2015-07-05 22:59:36 +00:00
|
|
|
::new(address_of(this->p_value)) Value(v.p_value);
|
2015-06-28 20:28:29 +00:00
|
|
|
this->p_engaged = v.p_engaged;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Maybe &operator=(Maybe &&v) {
|
|
|
|
if (this->p_engaged == v.p_engaged) {
|
2015-07-05 22:59:36 +00:00
|
|
|
if (this->p_engaged) this->p_value = move(v.p_value);
|
2015-06-28 20:28:29 +00:00
|
|
|
} else {
|
|
|
|
if (this->p_engaged)
|
|
|
|
this->p_value.~Value();
|
|
|
|
else {
|
2015-07-05 22:59:36 +00:00
|
|
|
::new(address_of(this->p_value)) Value(move(v.p_value));
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
this->p_engaged = v.p_engaged;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename U, typename = EnableIf<
|
|
|
|
IsSame<RemoveReference<U>, Value>::value &&
|
|
|
|
IsConstructible<Value, U>::value &&
|
|
|
|
IsAssignable<Value &, U>::value
|
2015-06-28 20:28:29 +00:00
|
|
|
>>
|
|
|
|
Maybe &operator=(U &&v) {
|
|
|
|
if (this->p_engaged) {
|
2015-07-05 22:59:36 +00:00
|
|
|
this->p_value = forward<U>(v);
|
2015-06-28 20:28:29 +00:00
|
|
|
} else {
|
2015-07-05 22:59:36 +00:00
|
|
|
::new(address_of(this->p_value)) Value(forward<U>(v));
|
2015-06-28 20:28:29 +00:00
|
|
|
this->p_engaged = true;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename ...A, typename = EnableIf<
|
|
|
|
IsConstructible<Value, A...>::value
|
2015-06-28 20:28:29 +00:00
|
|
|
>>
|
|
|
|
void emplace(A &&...args) {
|
2015-07-05 22:59:36 +00:00
|
|
|
*this = nothing;
|
|
|
|
::new(address_of(this->p_value)) Value(forward<A>(args)...);
|
2015-06-28 20:28:29 +00:00
|
|
|
this->p_engaged = true;
|
|
|
|
}
|
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename U, typename ...A, typename = EnableIf<
|
|
|
|
IsConstructible<Value, std::initializer_list<U> &, A...>::value
|
2015-06-28 20:28:29 +00:00
|
|
|
>>
|
|
|
|
void emplace(std::initializer_list<U> il, A &&...args) {
|
2015-07-05 22:59:36 +00:00
|
|
|
*this = nothing;
|
|
|
|
::new(address_of(this->p_value))
|
|
|
|
Value(il, forward<A>(args)...);
|
2015-06-28 20:28:29 +00:00
|
|
|
this->p_engaged = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
constexpr const Value *operator->() const {
|
2015-07-05 22:59:36 +00:00
|
|
|
return address_of(this->p_value);
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Value *operator->() {
|
2015-07-05 22:59:36 +00:00
|
|
|
return address_of(this->p_value);
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
constexpr const Value &operator*() const {
|
|
|
|
return this->p_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
Value &operator*() {
|
|
|
|
return this->p_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
constexpr explicit operator bool() const { return this->p_engaged; }
|
|
|
|
|
|
|
|
constexpr const Value &value() const {
|
|
|
|
return this->p_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
Value &value() {
|
|
|
|
return this->p_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
constexpr Value value_or(U &&v) const & {
|
2015-07-05 22:59:36 +00:00
|
|
|
static_assert(IsCopyConstructible<Value>::value,
|
2015-06-28 20:28:29 +00:00
|
|
|
"Maybe<T>::value_or: T must be copy constructible");
|
2015-07-05 22:59:36 +00:00
|
|
|
static_assert(IsConvertible<U, Value>::value,
|
2015-06-28 20:28:29 +00:00
|
|
|
"Maybe<T>::value_or: U must be convertible to T");
|
2015-07-05 22:59:36 +00:00
|
|
|
return this->p_engaged ? this->p_value : Value(forward<U>(v));
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
Value value_or(U &&v) && {
|
2015-07-05 22:59:36 +00:00
|
|
|
static_assert(IsMoveConstructible<Value>::value,
|
2015-06-28 20:28:29 +00:00
|
|
|
"Maybe<T>::value_or: T must be copy constructible");
|
2015-07-05 22:59:36 +00:00
|
|
|
static_assert(IsConvertible<U, Value>::value,
|
2015-06-28 20:28:29 +00:00
|
|
|
"Maybe<T>::value_or: U must be convertible to T");
|
2015-07-05 22:59:36 +00:00
|
|
|
return this->p_engaged ? move(this->p_value)
|
|
|
|
: Value(forward<U>(v));
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void swap(Maybe &v) {
|
|
|
|
if (this->p_engaged == v.p_engaged) {
|
2015-07-11 17:50:13 +00:00
|
|
|
if (this->p_engaged) detail::swap_adl(this->p_value, v.p_value);
|
2015-06-28 20:28:29 +00:00
|
|
|
} else {
|
|
|
|
if (this->p_engaged) {
|
2015-07-05 22:59:36 +00:00
|
|
|
::new(address_of(v.p_value)) Value(move(this->p_value));
|
2015-06-28 20:28:29 +00:00
|
|
|
this->p_value.~Value();
|
|
|
|
} else {
|
2015-07-05 22:59:36 +00:00
|
|
|
::new(address_of(this->p_value)) Value(move(v.p_value));
|
2015-06-28 20:28:29 +00:00
|
|
|
v.p_value.~Value();
|
|
|
|
}
|
2015-07-11 17:50:13 +00:00
|
|
|
detail::swap_adl(this->p_engaged, v.p_engaged);
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
Size to_hash() const {
|
2015-07-13 19:07:14 +00:00
|
|
|
return this->p_engaged ? ostd::ToHash<T>()(this->p_value) : 0;
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* maybe vs maybe */
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator==(const Maybe<T> &a, const Maybe<T> &b) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return (bool(a) != bool(b)) ? false : (!bool(a) ? true : (*a == *b));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator!=(const Maybe<T> &a, const Maybe<T> &b) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return !(a == b);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator<(const Maybe<T> &a, const Maybe<T> &b) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return !bool(b) ? false : (!bool(a) ? true : (*a < *b));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator>(const Maybe<T> &a, const Maybe<T> &b) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return b < a;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator<=(const Maybe<T> &a, const Maybe<T> &b) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return !(b < a);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator>=(const Maybe<T> &a, const Maybe<T> &b) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return !(a < b);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* maybe vs nothing */
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator==(const Maybe<T> &v, Nothing) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return !bool(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator==(Nothing, const Maybe<T> &v) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return !bool(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator!=(const Maybe<T> &v, Nothing) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return bool(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator!=(Nothing, const Maybe<T> &v) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return bool(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator<(const Maybe<T> &, Nothing) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator<(Nothing, const Maybe<T> &v) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return bool(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator<=(const Maybe<T> &v, Nothing) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return !bool(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator<=(Nothing, const Maybe<T> &) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator>(const Maybe<T> &v, Nothing) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return bool(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator>(Nothing, const Maybe<T> &) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator>=(const Maybe<T> &, Nothing) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator>=(Nothing, const Maybe<T> &v) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return !bool(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* maybe vs T */
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator==(const Maybe<T> &a, const T &b) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return bool(a) ? (*a == b) : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator==(const T &b, const Maybe<T> &a) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return bool(a) ? (*a == b) : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator!=(const Maybe<T> &a, const T &b) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return bool(a) ? !(*a == b) : true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator!=(const T &b, const Maybe<T> &a) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return bool(a) ? !(*a == b) : true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator<(const Maybe<T> &a, const T &b) {
|
2015-07-05 22:59:36 +00:00
|
|
|
return bool(a) ? Less<T>()(*a, b) : true;
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator<(const T &b, const Maybe<T> &a) {
|
2015-07-05 22:59:36 +00:00
|
|
|
return bool(a) ? Less<T>()(b, *a) : false;
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator<=(const Maybe<T> &a, const T &b) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return !(a > b);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator<=(const T &b, const Maybe<T> &a) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return !(b > a);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator>(const Maybe<T> &a, const T &b) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return bool(a) ? (b < a) : true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator>(const T &b, const Maybe<T> &a) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return bool(a) ? (a < b) : true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator>=(const Maybe<T> &a, const T &b) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return !(a < b);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr bool operator>=(const T &b, const Maybe<T> &a) {
|
2015-06-28 20:28:29 +00:00
|
|
|
return !(b < a);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* make maybe */
|
|
|
|
|
|
|
|
template<typename T>
|
2015-07-11 15:07:52 +00:00
|
|
|
inline constexpr Maybe<Decay<T>> make_maybe(T &&v) {
|
2015-07-05 22:59:36 +00:00
|
|
|
return Maybe<Decay<T>>(forward<T>(v));
|
2015-06-28 20:28:29 +00:00
|
|
|
}
|
|
|
|
|
2015-07-13 19:07:14 +00:00
|
|
|
} /* namespace ostd */
|
2015-06-28 20:28:29 +00:00
|
|
|
|
|
|
|
#endif
|