10 # ifndef WPIUTIL_WPI_OPTIONAL_H
11 # define WPIUTIL_WPI_OPTIONAL_H
14 # include <type_traits>
15 # include <initializer_list>
17 # include <functional>
21 # define TR2_OPTIONAL_REQUIRES(...) typename std::enable_if<__VA_ARGS__::value, bool>::type = false
23 # if defined __GNUC__ || (defined _MSC_VER) && (_MSC_VER >= 1910)
24 # define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1
25 # define OPTIONAL_CONSTEXPR_INIT_LIST constexpr
27 # define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0
28 # define OPTIONAL_CONSTEXPR_INIT_LIST
31 # if defined __clang__ && (defined __cplusplus) && (__cplusplus != 201103L)
32 # define OPTIONAL_HAS_MOVE_ACCESSORS 1
34 # define OPTIONAL_HAS_MOVE_ACCESSORS 0
43 template <
class T>
class optional<T&>;
47 template <
class T>
inline constexpr T&& constexpr_forward(
typename std::remove_reference<T>::type& t) noexcept
49 return static_cast<T&&
>(t);
52 template <
class T>
inline constexpr T&& constexpr_forward(
typename std::remove_reference<T>::type&& t) noexcept
54 static_assert(!std::is_lvalue_reference<T>::value,
"!!");
55 return static_cast<T&&
>(t);
58 template <
class T>
inline constexpr
typename std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept
60 return static_cast<typename std::remove_reference<T>::type&&
>(t);
65 # define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
67 # define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR)))
79 constexpr
static bool has_overload(...) {
return false; }
81 template <
class X,
size_t S = sizeof(std::declval<X&>().operator&()) >
82 constexpr
static bool has_overload(
bool) {
return true; }
84 constexpr
static bool value = has_overload<T>(
true);
87 template <
typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)>
88 constexpr T* static_addressof(T& ref)
93 template <
typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)>
94 T* static_addressof(T& ref)
96 return std::addressof(ref);
102 constexpr U convert(U v) {
return v; }
110 void adl_swap(T& t, T& u) noexcept(noexcept(swap(t, u)))
133 constexpr nullopt_t nullopt{nullopt_t::init()};
147 unsigned char dummy_;
152 template <
class... Args>
153 constexpr
storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
162 unsigned char dummy_;
167 template <
class... Args>
168 constexpr
constexpr_storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
170 ~constexpr_storage_t() =
default;
180 constexpr
optional_base() noexcept : init_(
false), storage_(trivial_init) {};
182 explicit constexpr
optional_base(
const T& v) : init_(
true), storage_(v) {}
184 explicit constexpr optional_base(T&& v) : init_(
true), storage_(constexpr_move(v)) {}
186 template <
class... Args>
explicit optional_base(
in_place_t, Args&&... args)
187 : init_(
true), storage_(constexpr_forward<Args>(args)...) {}
189 template <
class U,
class... Args, TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
190 explicit optional_base(
in_place_t, std::initializer_list<U> il, Args&&... args)
191 : init_(
true), storage_(il, std::forward<Args>(args)...) {}
193 ~optional_base() {
if (init_) storage_.value_.T::~T(); }
207 explicit constexpr constexpr_optional_base(T&& v) : init_(
true), storage_(constexpr_move(v)) {}
209 template <
class... Args>
explicit constexpr constexpr_optional_base(
in_place_t, Args&&... args)
210 : init_(
true), storage_(constexpr_forward<Args>(args)...) {}
212 template <
class U,
class... Args, TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
213 OPTIONAL_CONSTEXPR_INIT_LIST
explicit constexpr_optional_base(
in_place_t, std::initializer_list<U> il, Args&&... args)
214 : init_(
true), storage_(il, std::forward<Args>(args)...) {}
216 ~constexpr_optional_base() =
default;
220 using OptionalBase =
typename std::conditional<
221 std::is_trivially_destructible<T>::value,
229 class optional :
private OptionalBase<T>
231 static_assert( !std::is_same<
typename std::decay<T>::type,
nullopt_t>::value,
"bad T" );
232 static_assert( !std::is_same<
typename std::decay<T>::type,
in_place_t>::value,
"bad T" );
235 constexpr
bool initialized() const noexcept {
return OptionalBase<T>::init_; }
236 typename std::remove_const<T>::type* dataptr() {
return std::addressof(OptionalBase<T>::storage_.value_); }
237 constexpr
const T* dataptr()
const {
return detail_::static_addressof(OptionalBase<T>::storage_.value_); }
239 constexpr
const T& contained_val() const& {
return OptionalBase<T>::storage_.value_; }
240 # if OPTIONAL_HAS_MOVE_ACCESSORS == 1
241 constexpr T&& contained_val() && {
return std::move(OptionalBase<T>::storage_.value_); }
242 constexpr T& contained_val() & {
return OptionalBase<T>::storage_.value_; }
244 T& contained_val() & {
return OptionalBase<T>::storage_.value_; }
245 T&& contained_val() && {
return std::move(OptionalBase<T>::storage_.value_); }
248 void clear() noexcept {
249 if (initialized()) dataptr()->T::~T();
250 OptionalBase<T>::init_ =
false;
253 template <
class... Args>
254 void initialize(Args&&... args) noexcept(noexcept(T(
std::forward<Args>(args)...)))
256 assert(!OptionalBase<T>::init_);
257 ::new (static_cast<void*>(dataptr())) T(
std::forward<Args>(args)...);
258 OptionalBase<T>::init_ = true;
261 template <class U, class... Args>
262 void initialize(
std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il,
std::forward<Args>(args)...)))
264 assert(!OptionalBase<T>::init_);
265 ::new (static_cast<void*>(dataptr())) T(il,
std::forward<Args>(args)...);
266 OptionalBase<T>::init_ = true;
270 typedef T value_type;
273 constexpr optional() noexcept : OptionalBase<T>() {};
274 constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {};
276 optional(
const optional& rhs)
279 if (rhs.initialized()) {
280 ::new (static_cast<void*>(dataptr())) T(*rhs);
281 OptionalBase<T>::init_ = true;
285 optional(optional&& rhs) noexcept(
std::is_nothrow_move_constructible<T>::value)
288 if (rhs.initialized()) {
289 ::new (static_cast<void*>(dataptr())) T(
std::move(*rhs));
290 OptionalBase<T>::init_ = true;
294 constexpr optional(const T& v) : OptionalBase<T>(v) {}
296 constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {}
298 template <
class... Args>
299 explicit constexpr optional(in_place_t, Args&&... args)
300 : OptionalBase<T>(in_place_t{}, constexpr_forward<Args>(args)...) {}
302 template <
class U,
class... Args, TR2_OPTIONAL_REQUIRES(std::is_constructible<T, std::initializer_list<U>>)>
303 OPTIONAL_CONSTEXPR_INIT_LIST
explicit optional(in_place_t, std::initializer_list<U> il, Args&&... args)
304 : OptionalBase<T>(in_place_t{}, il, constexpr_forward<Args>(args)...) {}
307 ~optional() =
default;
310 optional& operator=(nullopt_t) noexcept
316 optional& operator=(
const optional& rhs)
318 if (initialized() ==
true && rhs.initialized() ==
false) clear();
319 else if (initialized() ==
false && rhs.initialized() ==
true) initialize(*rhs);
320 else if (initialized() ==
true && rhs.initialized() ==
true) contained_val() = *rhs;
324 optional& operator=(optional&& rhs)
325 noexcept(
std::is_nothrow_move_assignable<T>::value &&
std::is_nothrow_move_constructible<T>::value)
327 if (initialized() ==
true && rhs.initialized() ==
false) clear();
328 else if (initialized() ==
false && rhs.initialized() ==
true) initialize(std::move(*rhs));
329 else if (initialized() ==
true && rhs.initialized() ==
true) contained_val() = std::move(*rhs);
334 auto operator=(U&& v)
335 ->
typename std::enable_if
337 std::is_same<typename std::decay<U>::type, T>::value,
341 if (initialized()) { contained_val() = std::forward<U>(v); }
342 else { initialize(std::forward<U>(v)); }
347 template <
class... Args>
348 void emplace(Args&&... args)
351 initialize(std::forward<Args>(args)...);
354 template <
class U,
class... Args>
355 void emplace(std::initializer_list<U> il, Args&&... args)
358 initialize<U, Args...>(il, std::forward<Args>(args)...);
362 void swap(optional<T>& rhs) noexcept(std::is_nothrow_move_constructible<T>::value
363 && noexcept(detail_::swap_ns::adl_swap(std::declval<T&>(), std::declval<T&>())))
365 if (initialized() ==
true && rhs.initialized() ==
false) { rhs.initialize(std::move(**
this)); clear(); }
366 else if (initialized() ==
false && rhs.initialized() ==
true) { initialize(std::move(*rhs)); rhs.clear(); }
367 else if (initialized() ==
true && rhs.initialized() ==
true) {
using std::swap; swap(**
this, *rhs); }
372 explicit constexpr
operator bool() const noexcept {
return initialized(); }
373 constexpr
bool has_value() const noexcept {
return initialized(); }
375 constexpr T
const* operator ->()
const {
376 return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr());
379 # if OPTIONAL_HAS_MOVE_ACCESSORS == 1
381 constexpr T* operator ->() {
382 assert (initialized());
386 constexpr T
const& operator *() const& {
387 return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
390 constexpr T& operator *() & {
391 assert (initialized());
392 return contained_val();
395 constexpr T&& operator *() && {
396 assert (initialized());
397 return constexpr_move(contained_val());
400 constexpr T
const& value() const& {
401 return initialized() ? contained_val() : (throw bad_optional_access(
"bad optional access"), contained_val());
404 constexpr T& value() & {
405 return initialized() ? contained_val() : (throw bad_optional_access(
"bad optional access"), contained_val());
408 constexpr T&& value() && {
409 if (!initialized())
throw bad_optional_access(
"bad optional access");
410 return std::move(contained_val());
416 assert (initialized());
420 constexpr T
const& operator *()
const {
421 return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
425 assert (initialized());
426 return contained_val();
429 constexpr T
const& value()
const {
430 return initialized() ? contained_val() : (throw bad_optional_access(
"bad optional access"), contained_val());
434 return initialized() ? contained_val() : (throw bad_optional_access(
"bad optional access"), contained_val());
440 constexpr T value_or(V&& v) const&
442 return *
this ? **
this : detail_::convert<T>(constexpr_forward<V>(v));
445 # if OPTIONAL_HAS_MOVE_ACCESSORS == 1
448 constexpr T value_or(V&& v) &&
450 return *
this ? constexpr_move(
const_cast<optional<T>&
>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
458 return *
this ? constexpr_move(
const_cast<optional<T>&
>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
464 void reset() noexcept { clear(); }
471 static_assert( !std::is_same<T, nullopt_t>::value,
"bad T" );
472 static_assert( !std::is_same<T, in_place_t>::value,
"bad T" );
478 constexpr
optional() noexcept : ref(
nullptr) {}
482 constexpr
optional(T& v) noexcept : ref(detail_::static_addressof(v)) {}
488 explicit constexpr
optional(
in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {}
510 template <
typename U>
511 auto operator=(U&& rhs) noexcept
512 ->
typename std::enable_if
514 std::is_same<typename std::decay<U>::type,
optional<T&>>::value,
522 template <
typename U>
523 auto operator=(U&& rhs) noexcept
524 ->
typename std::enable_if
526 !std::is_same<typename std::decay<U>::type,
optional<T&>>::value,
531 void emplace(T& v) noexcept {
532 ref = detail_::static_addressof(v);
535 void emplace(T&&) =
delete;
540 std::swap(ref, rhs.ref);
544 constexpr T* operator->()
const {
545 return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref);
548 constexpr T& operator*()
const {
549 return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref);
552 constexpr T& value()
const {
556 explicit constexpr
operator bool()
const noexcept {
557 return ref !=
nullptr;
560 constexpr
bool has_value()
const noexcept {
561 return ref !=
nullptr;
565 constexpr
typename std::decay<T>::type value_or(V&& v)
const
567 return *
this ? **
this : detail_::convert<typename std::decay<T>::type>(constexpr_forward<V>(v));
571 void reset() noexcept { ref =
nullptr; }
578 static_assert(
sizeof(T) == 0,
"optional rvalue references disallowed" );
585 return bool(x) != bool(y) ?
false : bool(x) ==
false ?
true : *x == *y;
588 template <
class T> constexpr
bool operator!=(
const optional<T>& x,
const optional<T>& y)
593 template <
class T> constexpr
bool operator<(const optional<T>& x,
const optional<T>& y)
595 return (!y) ?
false : (!x) ?
true : *x < *y;
598 template <
class T> constexpr
bool operator>(
const optional<T>& x,
const optional<T>& y)
603 template <
class T> constexpr
bool operator<=(const optional<T>& x,
const optional<T>& y)
608 template <
class T> constexpr
bool operator>=(
const optional<T>& x,
const optional<T>& y)
615 template <
class T> constexpr
bool operator==(
const optional<T>& x, nullopt_t) noexcept
620 template <
class T> constexpr
bool operator==(nullopt_t,
const optional<T>& x) noexcept
625 template <
class T> constexpr
bool operator!=(
const optional<T>& x, nullopt_t) noexcept
630 template <
class T> constexpr
bool operator!=(nullopt_t,
const optional<T>& x) noexcept
635 template <
class T> constexpr
bool operator<(const optional<T>&, nullopt_t) noexcept
640 template <
class T> constexpr
bool operator<(nullopt_t, const optional<T>& x) noexcept
645 template <
class T> constexpr
bool operator<=(const optional<T>& x, nullopt_t) noexcept
650 template <
class T> constexpr
bool operator<=(nullopt_t, const optional<T>&) noexcept
655 template <
class T> constexpr
bool operator>(
const optional<T>& x, nullopt_t) noexcept
660 template <
class T> constexpr
bool operator>(nullopt_t,
const optional<T>&) noexcept
665 template <
class T> constexpr
bool operator>=(
const optional<T>&, nullopt_t) noexcept
670 template <
class T> constexpr
bool operator>=(nullopt_t,
const optional<T>& x) noexcept
678 template <
class T> constexpr
bool operator==(
const optional<T>& x,
const T& v)
680 return bool(x) ? *x == v :
false;
683 template <
class T> constexpr
bool operator==(
const T& v,
const optional<T>& x)
685 return bool(x) ? v == *x :
false;
688 template <
class T> constexpr
bool operator!=(
const optional<T>& x,
const T& v)
690 return bool(x) ? *x != v :
true;
693 template <
class T> constexpr
bool operator!=(
const T& v,
const optional<T>& x)
695 return bool(x) ? v != *x :
true;
698 template <
class T> constexpr
bool operator<(const optional<T>& x,
const T& v)
700 return bool(x) ? *x < v :
true;
703 template <
class T> constexpr
bool operator>(
const T& v,
const optional<T>& x)
705 return bool(x) ? v > *x :
true;
708 template <
class T> constexpr
bool operator>(
const optional<T>& x,
const T& v)
710 return bool(x) ? *x > v :
false;
713 template <
class T> constexpr
bool operator<(const T& v, const optional<T>& x)
715 return bool(x) ? v < *x :
false;
718 template <
class T> constexpr
bool operator>=(
const optional<T>& x,
const T& v)
720 return bool(x) ? *x >= v :
false;
723 template <
class T> constexpr
bool operator<=(const T& v, const optional<T>& x)
725 return bool(x) ? v <= *x :
false;
728 template <
class T> constexpr
bool operator<=(const optional<T>& x,
const T& v)
730 return bool(x) ? *x <= v :
true;
733 template <
class T> constexpr
bool operator>=(
const T& v,
const optional<T>& x)
735 return bool(x) ? v >= *x :
true;
740 template <
class T> constexpr
bool operator==(
const optional<T&>& x,
const T& v)
742 return bool(x) ? *x == v :
false;
745 template <
class T> constexpr
bool operator==(
const T& v,
const optional<T&>& x)
747 return bool(x) ? v == *x :
false;
750 template <
class T> constexpr
bool operator!=(
const optional<T&>& x,
const T& v)
752 return bool(x) ? *x != v :
true;
755 template <
class T> constexpr
bool operator!=(
const T& v,
const optional<T&>& x)
757 return bool(x) ? v != *x :
true;
760 template <
class T> constexpr
bool operator<(const optional<T&>& x,
const T& v)
762 return bool(x) ? *x < v :
true;
765 template <
class T> constexpr
bool operator>(
const T& v,
const optional<T&>& x)
767 return bool(x) ? v > *x :
true;
770 template <
class T> constexpr
bool operator>(
const optional<T&>& x,
const T& v)
772 return bool(x) ? *x > v :
false;
775 template <
class T> constexpr
bool operator<(const T& v, const optional<T&>& x)
777 return bool(x) ? v < *x :
false;
780 template <
class T> constexpr
bool operator>=(
const optional<T&>& x,
const T& v)
782 return bool(x) ? *x >= v :
false;
785 template <
class T> constexpr
bool operator<=(const T& v, const optional<T&>& x)
787 return bool(x) ? v <= *x :
false;
790 template <
class T> constexpr
bool operator<=(const optional<T&>& x,
const T& v)
792 return bool(x) ? *x <= v :
true;
795 template <
class T> constexpr
bool operator>=(
const T& v,
const optional<T&>& x)
797 return bool(x) ? v >= *x :
true;
801 template <
class T> constexpr
bool operator==(
const optional<const T&>& x,
const T& v)
803 return bool(x) ? *x == v :
false;
806 template <
class T> constexpr
bool operator==(
const T& v,
const optional<const T&>& x)
808 return bool(x) ? v == *x :
false;
811 template <
class T> constexpr
bool operator!=(
const optional<const T&>& x,
const T& v)
813 return bool(x) ? *x != v :
true;
816 template <
class T> constexpr
bool operator!=(
const T& v,
const optional<const T&>& x)
818 return bool(x) ? v != *x :
true;
821 template <
class T> constexpr
bool operator<(const optional<const T&>& x,
const T& v)
823 return bool(x) ? *x < v :
true;
826 template <
class T> constexpr
bool operator>(
const T& v,
const optional<const T&>& x)
828 return bool(x) ? v > *x :
true;
831 template <
class T> constexpr
bool operator>(
const optional<const T&>& x,
const T& v)
833 return bool(x) ? *x > v :
false;
836 template <
class T> constexpr
bool operator<(const T& v, const optional<const T&>& x)
838 return bool(x) ? v < *x :
false;
841 template <
class T> constexpr
bool operator>=(
const optional<const T&>& x,
const T& v)
843 return bool(x) ? *x >= v :
false;
846 template <
class T> constexpr
bool operator<=(const T& v, const optional<const T&>& x)
848 return bool(x) ? v <= *x :
false;
851 template <
class T> constexpr
bool operator<=(const optional<const T&>& x,
const T& v)
853 return bool(x) ? *x <= v :
true;
856 template <
class T> constexpr
bool operator>=(
const T& v,
const optional<const T&>& x)
858 return bool(x) ? v >= *x :
true;
864 void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)))
871 constexpr optional<typename std::decay<T>::type> make_optional(T&& v)
873 return optional<typename std::decay<T>::type>(constexpr_forward<T>(v));
877 constexpr optional<X&> make_optional(std::reference_wrapper<X> v)
879 return optional<X&>(v.get());
887 template <
typename T>
888 struct hash<
wpi::optional<T>>
890 typedef typename hash<T>::result_type result_type;
893 constexpr result_type operator()(argument_type
const& arg)
const {
894 return arg ? std::hash<T>{}(*arg) : result_type{};
898 template <
typename T>
899 struct hash<
wpi::optional<T&>>
901 typedef typename hash<T>::result_type result_type;
904 constexpr result_type operator()(argument_type
const& arg)
const {
905 return arg ? std::hash<T>{}(*arg) : result_type{};
910 # undef TR2_OPTIONAL_REQUIRES
911 # undef TR2_OPTIONAL_ASSERTED_EXPRESSION
913 # endif //WPIUTIL_WPI_OPTIONAL_H
Definition: optional.h:40
Definition: optional.h:120
Definition: optional.h:175
Definition: optional.h:128
Definition: optional.h:76
Definition: optional.h:885
Definition: optional.h:124
WPILib C++ utilities (wpiutil) namespace.
Definition: SmallString.h:21
Definition: optional.h:160
Definition: optional.h:137
Definition: optional.h:198
Definition: optional.h:130
Definition: optional.h:469
Definition: optional.h:145