1515
1616#include < mrdocs/Platform.hpp>
1717#include < mrdocs/ADT/Nullable.hpp>
18- #include < compare>
1918#include < optional>
2019#include < type_traits>
2120#include < utility>
@@ -84,11 +83,6 @@ class Optional {
8483 }())
8584 {}
8685
87- /* * Construct from std::nullopt
88- */
89- constexpr Optional (std::nullopt_t ) noexcept (default_ctor_noex_())
90- : Optional() {}
91-
9286 // / Copy constructor
9387 constexpr Optional (Optional const &) = default;
9488
@@ -108,18 +102,15 @@ class Optional {
108102 @param u The value to store. It must be convertible to T.
109103 **/
110104 template <class U >
111- requires (
112- !std::same_as<std::remove_cvref_t <U>, Optional>
113- && !std::same_as<std::remove_cvref_t <U>, std::in_place_t >
114- && !std::same_as<std::remove_cvref_t <U>, std::nullopt_t >
115- && std::is_constructible_v<T, U>)
105+ requires std::is_constructible_v<T, U>
116106 constexpr explicit Optional (U&& u) noexcept (
117107 std::is_nothrow_constructible_v<T, U>)
118108 : s_([&] {
119109 if constexpr (uses_nullable_traits)
120110 {
121111 return storage_t (static_cast <T>(std::forward<U>(u)));
122- } else
112+ }
113+ else
123114 {
124115 return storage_t (std::forward<U>(u));
125116 }
@@ -131,20 +122,11 @@ class Optional {
131122 @param u The value to store. It must be convertible to T.
132123 **/
133124 template <class U >
134- requires (
135- !std::same_as<std::remove_cvref_t <U>, Optional>
136- && std::is_constructible_v<T, U> && std::is_assignable_v<T&, U>)
137- constexpr
138- Optional&
125+ requires std::is_constructible_v<T, U> && std::is_assignable_v<T&, U>
126+ constexpr Optional&
139127 operator =(U&& u) noexcept (std::is_nothrow_assignable_v<T&, U>)
140128 {
141- if constexpr (uses_nullable_traits)
142- {
143- s_ = std::forward<U>(u);
144- } else
145- {
146- s_ = std::forward<U>(u);
147- }
129+ s_ = std::forward<U>(u);
148130 return *this ;
149131 }
150132
@@ -348,311 +330,15 @@ class Optional {
348330 return *s_;
349331 }
350332 }
351- };
352-
353- namespace detail {
354- template <typename T>
355- inline constexpr bool isOptionalV = false ;
356333
357- template <typename T>
358- inline constexpr bool isOptionalV<Optional<T>> = true ;
359-
360- template <typename T>
361- using OptionalRelopT = std::enable_if_t <std::is_convertible_v<T, bool >, bool >;
362-
363- template <typename T, typename U>
364- using OptionalEqT = OptionalRelopT<
365- decltype (std::declval<T const &>() == std::declval<U const &>())>;
366-
367- template <typename T, typename U>
368- using OptionalNeT = OptionalRelopT<
369- decltype (std::declval<T const &>() != std::declval<U const &>())>;
370-
371- template <typename T, typename U>
372- using OptionalLtT = OptionalRelopT<
373- decltype (std::declval<T const &>() < std::declval<U const &>())>;
374-
375- template <typename T, typename U>
376- using OptionalGtT = OptionalRelopT<
377- decltype (std::declval<T const &>() > std::declval<U const &>())>;
378-
379- template <typename T, typename U>
380- using OptionalLeT = OptionalRelopT<
381- decltype (std::declval<T const &>() <= std::declval<U const &>())>;
382-
383- template <typename T, typename U>
384- using OptionalGeT = detail::OptionalRelopT<
385- decltype (std::declval<T const &>() >= std::declval<U const &>())>;
386-
387- template <typename T>
388- concept isDerivedFromOptional = requires (T const & __t ) {
389- []<typename U>(Optional<U> const &) {
390- }(__t );
334+ /* * Three-way comparison defaults when supported by the underlying
335+ T/std::optional.
336+ **/
337+ auto
338+ operator <=>(Optional const &) const
339+ = default ;
391340};
392341
393- } // namespace detail
394-
395- /* * Compares two Optional values for equality.
396-
397- Returns true if both are engaged and their contained values are equal, or both are disengaged.
398- */
399- template <typename T, typename U>
400- constexpr detail::OptionalEqT<T, U>
401- operator ==(Optional<T> const & lhs, Optional<U> const & rhs)
402- {
403- return static_cast <bool >(lhs) == static_cast <bool >(rhs)
404- && (!lhs || *lhs == *rhs);
405- }
406-
407- /* * Compares two Optional values for inequality.
408-
409- Returns true if their engagement states differ or their contained values are not equal.
410- */
411- template <typename T, typename U>
412- constexpr detail::OptionalNeT<T, U>
413- operator !=(Optional<T> const & lhs, Optional<U> const & rhs)
414- {
415- return static_cast <bool >(lhs) != static_cast <bool >(rhs)
416- || (static_cast <bool >(lhs) && *lhs != *rhs);
417- }
418-
419- /* * Checks if the left Optional is less than the right Optional.
420-
421- Returns true if the right is engaged and either the left is disengaged or its value is less.
422- */
423- template <typename T, typename U>
424- constexpr detail::OptionalLtT<T, U>
425- operator <(Optional<T> const & lhs, Optional<U> const & rhs)
426- {
427- return static_cast <bool >(rhs) && (!lhs || *lhs < *rhs);
428- }
429-
430- /* * Checks if the left Optional is greater than the right Optional.
431-
432- Returns true if the left is engaged and either the right is disengaged or its value is greater.
433- */
434- template <typename T, typename U>
435- constexpr detail::OptionalGtT<T, U>
436- operator >(Optional<T> const & lhs, Optional<U> const & rhs)
437- {
438- return static_cast <bool >(lhs) && (!rhs || *lhs > *rhs);
439- }
440-
441- /* * Checks if the left Optional is less than or equal to the right Optional.
442-
443- Returns true if the left is disengaged or the right is engaged and the left's value is less or equal.
444- */
445- template <typename T, typename U>
446- constexpr detail::OptionalLeT<T, U>
447- operator <=(Optional<T> const & lhs, Optional<U> const & rhs)
448- {
449- return !lhs || (static_cast <bool >(rhs) && *lhs <= *rhs);
450- }
451-
452- /* * Checks if the left Optional is greater than or equal to the right Optional.
453-
454- Returns true if the right is disengaged or the left is engaged and its value is greater or equal.
455- */
456- template <typename T, typename U>
457- constexpr detail::OptionalGeT<T, U>
458- operator >=(Optional<T> const & lhs, Optional<U> const & rhs)
459- {
460- return !rhs || (static_cast <bool >(lhs) && *lhs >= *rhs);
461- }
462-
463- /* * Performs a three-way comparison between two Optional values.
464-
465- If both are engaged, compares their contained values; otherwise, compares engagement state.
466- */
467- template <typename T, std::three_way_comparable_with<T> U>
468- [[nodiscard]]
469- constexpr std::compare_three_way_result_t <T, U>
470- operator <=>(Optional<T> const & x, Optional<U> const & y)
471- {
472- return x && y ? *x <=> *y : bool (x) <=> bool (y);
473- }
474-
475- /* * Checks if the Optional is disengaged (equal to std::nullopt).
476-
477- Returns true if the Optional does not contain a value.
478- */
479- template <typename T>
480- [[nodiscard]]
481- constexpr bool
482- operator ==(Optional<T> const & lhs, std::nullopt_t ) noexcept
483- {
484- return !lhs;
485- }
486-
487- /* * Performs a three-way comparison between an Optional and std::nullopt.
488-
489- Returns std::strong_ordering::greater if engaged, std::strong_ordering::equal if disengaged.
490- */
491- template <typename T>
492- [[nodiscard]]
493- constexpr std::strong_ordering
494- operator <=>(Optional<T> const & x, std::nullopt_t ) noexcept
495- {
496- return bool (x) <=> false ;
497- }
498-
499- /* * Compares an engaged Optional to a value for equality.
500-
501- Returns true if the Optional is engaged and its value equals rhs.
502- */
503- template <typename T, typename U>
504- requires (!detail::isOptionalV<U>)
505- constexpr detail::OptionalEqT<T, U>
506- operator == [[nodiscard]] (Optional<T> const & lhs, U const & rhs)
507- {
508- return lhs && *lhs == rhs;
509- }
510-
511- /* * Compares a value to an engaged Optional for equality.
512-
513- Returns true if the Optional is engaged and its value equals lhs.
514- */
515- template <typename T, typename U>
516- requires (!detail::isOptionalV<T>)
517- constexpr detail::OptionalEqT<T, U>
518- operator == [[nodiscard]] (T const & lhs, Optional<U> const & rhs)
519- {
520- return rhs && lhs == *rhs;
521- }
522-
523- /* * Compares an Optional to a value for inequality.
524-
525- Returns true if the Optional is disengaged or its value does not equal rhs.
526- */
527- template <typename T, typename U>
528- requires (!detail::isOptionalV<U>)
529- constexpr detail::OptionalNeT<T, U>
530- operator != [[nodiscard]] (Optional<T> const & lhs, U const & rhs)
531- {
532- return !lhs || *lhs != rhs;
533- }
534-
535- /* * Compares a value to an Optional for inequality.
536-
537- Returns true if the Optional is disengaged or its value does not equal lhs.
538- */
539- template <typename T, typename U>
540- requires (!detail::isOptionalV<T>)
541- constexpr detail::OptionalNeT<T, U>
542- operator != [[nodiscard]] (T const & lhs, Optional<U> const & rhs)
543- {
544- return !rhs || lhs != *rhs;
545- }
546-
547- /* * Checks if the Optional is less than a value.
548-
549- Returns true if the Optional is disengaged or its value is less than rhs.
550- */
551- template <typename T, typename U>
552- requires (!detail::isOptionalV<U>)
553- constexpr detail::OptionalLtT<T, U>
554- operator <[[nodiscard]] (Optional<T> const & lhs, U const & rhs)
555- {
556- return !lhs || *lhs < rhs;
557- }
558-
559- /* * Checks if a value is less than an engaged Optional.
560-
561- Returns true if the Optional is engaged and lhs is less than its value.
562- */
563- template <typename T, typename U>
564- requires (!detail::isOptionalV<T>)
565- constexpr detail::OptionalLtT<T, U>
566- operator <[[nodiscard]] (T const & lhs, Optional<U> const & rhs)
567- {
568- return rhs && lhs < *rhs;
569- }
570-
571- /* * Checks if the Optional is greater than a value.
572-
573- Returns true if the Optional is engaged and its value is greater than rhs.
574- */
575- template <typename T, typename U>
576- requires (!detail::isOptionalV<U>)
577- constexpr detail::OptionalGtT<T, U>
578- operator > [[nodiscard]] (Optional<T> const & lhs, U const & rhs)
579- {
580- return lhs && *lhs > rhs;
581- }
582-
583- /* * Checks if a value is greater than an Optional.
584-
585- Returns true if the Optional is disengaged or lhs is greater than its value.
586- */
587- template <typename T, typename U>
588- requires (!detail::isOptionalV<T>)
589- constexpr detail::OptionalGtT<T, U>
590- operator > [[nodiscard]] (T const & lhs, Optional<U> const & rhs)
591- {
592- return !rhs || lhs > *rhs;
593- }
594-
595- /* * Checks if the Optional is less than or equal to a value.
596-
597- Returns true if the Optional is disengaged or its value is less than or equal to rhs.
598- */
599- template <typename T, typename U>
600- requires (!detail::isOptionalV<U>)
601- constexpr detail::OptionalLeT<T, U>
602- operator <= [[nodiscard]] (Optional<T> const & lhs, U const & rhs)
603- {
604- return !lhs || *lhs <= rhs;
605- }
606-
607- /* * Checks if a value is less than or equal to an engaged Optional.
608-
609- Returns true if the Optional is engaged and lhs is less than or equal to its value.
610- */
611- template <typename T, typename U>
612- requires (!detail::isOptionalV<T>)
613- constexpr detail::OptionalLeT<T, U>
614- operator <= [[nodiscard]] (T const & lhs, Optional<U> const & rhs)
615- {
616- return rhs && lhs <= *rhs;
617- }
618-
619- /* * Checks if the Optional is greater than or equal to a value.
620-
621- Returns true if the Optional is engaged and its value is greater than or equal to rhs.
622- */
623- template <typename T, typename U>
624- requires (!detail::isOptionalV<U>)
625- constexpr detail::OptionalGeT<T, U>
626- operator >= [[nodiscard]] (Optional<T> const & lhs, U const & rhs)
627- {
628- return lhs && *lhs >= rhs;
629- }
630-
631- /* * Checks if a value is greater than or equal to an Optional.
632-
633- Returns true if the Optional is disengaged or lhs is greater than or equal to its value.
634- */
635- template <typename T, typename U>
636- requires (!detail::isOptionalV<T>)
637- constexpr detail::OptionalGeT<T, U>
638- operator >= [[nodiscard]] (T const & lhs, Optional<U> const & rhs)
639- {
640- return !rhs || lhs >= *rhs;
641- }
642-
643- /* * Performs a three-way comparison between an Optional and a value.
644-
645- If the Optional is engaged, compares its value to v; otherwise, returns less.
646- */
647- template <typename T, typename U>
648- requires (!detail::isDerivedFromOptional<U>)
649- && requires { typename std::compare_three_way_result_t <T, U>; }
650- && std::three_way_comparable_with<T, U>
651- constexpr std::compare_three_way_result_t <T, U>
652- operator <=> [[nodiscard]] (Optional<T> const & x, U const & v)
653- {
654- return bool (x) ? *x <=> v : std::strong_ordering::less;
655- }
656342} // namespace clang::mrdocs
657343
658344#endif
0 commit comments