27
27
#include " subspace/assertions/unreachable.h"
28
28
#include " subspace/construct/default.h"
29
29
#include " subspace/fn/fn_concepts.h"
30
+ #include " subspace/fn/run_fn.h"
30
31
#include " subspace/iter/from_iterator.h"
31
32
#include " subspace/iter/into_iterator.h"
32
33
#include " subspace/macros/always_inline.h"
@@ -81,13 +82,18 @@ using sus::iter::Once;
81
82
using sus::option::__private::Storage;
82
83
using sus::option::__private::StoragePointer;
83
84
84
- // / A type which either holds #Some value of type `T`, or #None.
85
+ // / A type which either holds `Some` value of type `T`, or `None`.
86
+ // /
87
+ // / To immediately pull the inner value out of an Option, use `unwrap()`. If the
88
+ // / `Option` is an lvalue, use `operator*` and `operator->` to access the inner
89
+ // / value. However if doing this many times, consider doing `unwrap()` a single
90
+ // / time up front.
85
91
// /
86
92
// / `Option<const T>` for non-reference-type `T` is disallowed, as the Option
87
93
// / owns the `T` in that case and it ensures the `Option` and the `T` are both
88
94
// / accessed with the same const-ness.
89
95
// /
90
- // / If a type `T` satisties `sus::mem::NeverValueField`, then Option<T> will
96
+ // / If a type `T` satisties `sus::mem::NeverValueField`, then ` Option<T>` will
91
97
// / have the same size as T.
92
98
template <class T >
93
99
class Option final {
@@ -101,7 +107,7 @@ class Option final {
101
107
public:
102
108
// / Default-construct an Option that is holding no value.
103
109
// /
104
- // / The Option's contained type `T` must be # Default.
110
+ // / The Option's contained type `T` must satisfy `sus::construct:: Default` .
105
111
inline constexpr Option () noexcept = default;
106
112
107
113
// / Construct an Option that is holding the given value.
@@ -123,7 +129,7 @@ class Option final {
123
129
}
124
130
}
125
131
126
- static inline constexpr Option some (T t) noexcept
132
+ static inline constexpr Option some (T& t) noexcept
127
133
requires(std::is_reference_v<T>)
128
134
{
129
135
return Option (move_to_storage (t));
@@ -442,13 +448,11 @@ class Option final {
442
448
443
449
// / Returns the contained value inside the Option, if there is one.
444
450
// / Otherwise, returns the result of the given function.
445
- template <class Functor >
446
- requires (std::is_same_v<std::invoke_result_t <Functor>, T>)
447
- constexpr T unwrap_or_else (Functor f) && noexcept {
451
+ constexpr T unwrap_or_else (::sus::fn::FnOnce<T()> auto&& f) && noexcept {
448
452
if (t_.state () == Some) {
449
453
return t_.take_and_set_none ();
450
454
} else {
451
- return f ( );
455
+ return :: sus::run_once (:: sus::move (f) );
452
456
}
453
457
}
454
458
@@ -517,8 +521,9 @@ class Option final {
517
521
// / This method differs from <unwrap_or_else>() in that it does not consume
518
522
// / the Option, and instead it can not be called on rvalues.
519
523
T& get_or_insert_with (::sus::fn::FnOnce<T()> auto&& f) & noexcept {
520
- if (t_.state () == None)
521
- t_.construct_from_none (move_to_storage (::sus::move (f)()));
524
+ if (t_.state () == None) {
525
+ t_.construct_from_none (move_to_storage (::sus::run_once (::sus::move (f))));
526
+ }
522
527
return t_.val_mut ();
523
528
}
524
529
@@ -542,11 +547,11 @@ class Option final {
542
547
// /
543
548
// / Returns an `Option<R>` in state #None if the current Option is in state
544
549
// / #None.
545
- constexpr auto map (
546
- ::sus::fn::FnOnce<::sus::fn::NonVoid(T&&)> auto&& m) && noexcept {
547
- using R = std:: invoke_result_t < decltype (m), T&&>;
550
+ template <::sus::fn::FnOnce<::sus::fn::NonVoid(T&&)> MapFn, int &...,
551
+ class R = std:: invoke_result_t <MapFn&&, T&&>>
552
+ constexpr auto map (MapFn&& m) && noexcept {
548
553
if (t_.state () == Some) {
549
- return Option<R>(::sus::move (m)( t_.take_and_set_none ()));
554
+ return Option<R>(::sus::run_once (:: sus:: move (m), t_.take_and_set_none ()));
550
555
} else {
551
556
return Option<R>::none ();
552
557
}
@@ -562,23 +567,24 @@ class Option final {
562
567
class R = std::invoke_result_t <MapFn&&, T&&>>
563
568
constexpr R map_or (R default_result, MapFn&& m) && noexcept {
564
569
if (t_.state () == Some) {
565
- return ::sus::move (m)( t_.take_and_set_none ());
570
+ return ::sus::run_once (:: sus:: move (m), t_.take_and_set_none ());
566
571
} else {
567
572
return default_result;
568
573
}
569
574
}
570
575
571
576
// / Computes a default function result (if none), or applies a different
572
577
// / function to the contained value (if any).
573
- template <class DefaultFn , class MapFn , int &...,
578
+ template <::sus::fn::FnOnce<::sus::fn::NonVoid()> DefaultFn,
579
+ ::sus::fn::FnOnce<::sus::fn::NonVoid(T&&)> MapFn, int &...,
574
580
class D = std::invoke_result_t <DefaultFn>,
575
581
class R = std::invoke_result_t <MapFn, T&&>>
576
- requires (!std::is_void_v<R> && std::is_same_v<D, R>)
577
- constexpr R map_or_else(DefaultFn default_fn, MapFn m) && noexcept {
582
+ requires (std::is_same_v<D, R>)
583
+ constexpr R map_or_else(DefaultFn&& default_fn, MapFn&& m) && noexcept {
578
584
if (t_.state () == Some) {
579
- return m ( t_.take_and_set_none ());
585
+ return :: sus::run_once (:: sus::move (m), t_.take_and_set_none ());
580
586
} else {
581
- return default_fn ( );
587
+ return :: sus::run_once (:: sus::move (default_fn) );
582
588
}
583
589
}
584
590
@@ -588,11 +594,10 @@ class Option final {
588
594
// / #None.
589
595
// /
590
596
// / The predicate function must take `const T&` and return `bool`.
591
- template <class Predicate >
592
- requires (std::is_same_v<std::invoke_result_t <Predicate, const T&>, bool >)
593
- constexpr Option<T> filter(Predicate p) && noexcept {
597
+ constexpr Option<T> filter (
598
+ ::sus::fn::FnOnce<bool (const T&)> auto&& p) && noexcept {
594
599
if (t_.state () == Some) {
595
- if (p ( t_.val ())) {
600
+ if (:: sus::run_once (:: sus::move (p), t_.val ())) {
596
601
return Option (t_.take_and_set_none ());
597
602
} else {
598
603
// The state has to become None, and we must destroy the inner T.
@@ -617,19 +622,22 @@ class Option final {
617
622
}
618
623
619
624
// / Consumes this Option and returns an Option with #None if this Option holds
620
- // / #None, otherwise calls `f` with the contained value and returns an Option
621
- // / with the result.
625
+ // / #None, otherwise calls `f` with the contained value and returns the
626
+ // / result.
627
+ // /
628
+ // / The function `f` receives the Option's inner `T` and can return any
629
+ // / `Option<U>`.
622
630
// /
623
631
// / Some languages call this operation flatmap.
624
- template <
625
- class AndFn , int &..., class R = std::invoke_result_t <AndFn, T&&>,
626
- class InnerR = ::sus::option::__private::IsOptionType<R>::inner_type>
632
+ template <::sus::fn::FnOnce<::sus::fn::NonVoid(T&&)> AndFn, int &...,
633
+ class R = std::invoke_result_t <AndFn, T&&>,
634
+ class U = ::sus::option::__private::IsOptionType<R>::inner_type>
627
635
requires (::sus::option::__private::IsOptionType<R>::value)
628
- constexpr Option<InnerR > and_then(AndFn f) && noexcept {
636
+ constexpr Option<U > and_then(AndFn&& f) && noexcept {
629
637
if (t_.state () == Some)
630
- return f ( t_.take_and_set_none ());
638
+ return :: sus::run_once (:: sus::move (f), t_.take_and_set_none ());
631
639
else
632
- return Option<InnerR >::none ();
640
+ return Option<U >::none ();
633
641
}
634
642
635
643
// / Consumes and returns an Option with the same value if this Option contains
@@ -643,13 +651,12 @@ class Option final {
643
651
644
652
// / Consumes and returns an Option with the same value if this Option contains
645
653
// / a value, otherwise returns the Option returned by `f`.
646
- template <class ElseFn , int &..., class R = std::invoke_result_t <ElseFn>>
647
- requires (std::is_same_v<R, Option<T>>)
648
- constexpr Option<T> or_else(ElseFn f) && noexcept {
654
+ constexpr Option<T> or_else (
655
+ ::sus::fn::FnOnce<Option<T>()> auto&& f) && noexcept {
649
656
if (t_.state () == Some)
650
657
return Option (t_.take_and_set_none ());
651
658
else
652
- return ::sus::move (f)( );
659
+ return ::sus::run_once (:: sus:: move (f));
653
660
}
654
661
655
662
// / Consumes this Option and returns an Option, holding the value from either
@@ -694,15 +701,16 @@ class Option final {
694
701
// / `Ok(v)` and `None` to `Err(f())`.
695
702
//
696
703
// TODO: No refs in Result: https://github.com/chromium/subspace/issues/133
697
- template <class ElseFn , int &..., class E = std::invoke_result_t <ElseFn>,
704
+ template <::sus::fn::FnOnce<::sus::fn::NonVoid()> ElseFn, int &...,
705
+ class E = std::invoke_result_t <ElseFn>,
698
706
class Result = ::sus::result::Result<T, E>>
699
- constexpr Result ok_or_else (ElseFn f) && noexcept
707
+ constexpr Result ok_or_else (ElseFn&& f) && noexcept
700
708
requires(!std::is_reference_v<T> && !std::is_reference_v<E>)
701
709
{
702
710
if (t_.state () == Some)
703
711
return Result::with (t_.take_and_set_none ());
704
712
else
705
- return Result::with_err (::sus::move (f)( ));
713
+ return Result::with_err (::sus::run_once (:: sus:: move (f)));
706
714
}
707
715
708
716
// / Transposes an #Option of a #Result into a #Result of an #Option.
@@ -836,10 +844,13 @@ class Option final {
836
844
// Calling as_ref() on an rvalue is not returning a reference to the inner
837
845
// value if the inner value is already a reference, so we allow calling it on
838
846
// an rvalue Option in that case.
839
- constexpr Option<const std::remove_reference_t <T>&> as_ref () const && noexcept
847
+ constexpr Option<const std::remove_reference_t <T>&> as_ref () && noexcept
840
848
requires(std::is_reference_v<T>)
841
849
{
842
- return as_ref ();
850
+ if (t_.state () == None)
851
+ return Option<const std::remove_reference_t <T>&>::none ();
852
+ else
853
+ return Option<const std::remove_reference_t <T>&>(t_.take_and_set_none ());
843
854
}
844
855
845
856
// / Returns an Option<T&> from this Option<T>, that either holds #None or a
@@ -853,18 +864,31 @@ class Option final {
853
864
// Calling as_mut() on an rvalue is not returning a reference to the inner
854
865
// value if the inner value is already a reference, so we allow calling it on
855
866
// an rvalue Option in that case.
856
- constexpr Option<const std:: remove_reference_t <T> &> as_mut () && noexcept
867
+ constexpr Option<T &> as_mut () && noexcept
857
868
requires(std::is_reference_v<T>)
858
869
{
859
- return as_mut ();
870
+ if (t_.state () == None)
871
+ return Option<T&>::none ();
872
+ else
873
+ return Option<T&>(t_.take_and_set_none ());
860
874
}
861
875
862
876
constexpr Once<const std::remove_reference_t <T>&> iter () const & noexcept {
863
877
return Once<const std::remove_reference_t <T>&>::with (as_ref ());
864
878
}
865
- constexpr Once<const T&> iter () const && = delete;
879
+ constexpr Once<const std::remove_reference_t <T>&> iter () && noexcept
880
+ requires(std::is_reference_v<T>)
881
+ {
882
+ return Once<const std::remove_reference_t <T>&>::with (
883
+ ::sus::move (*this ).as_ref());
884
+ }
866
885
867
886
constexpr Once<T&> iter_mut () & noexcept { return Once<T&>::with (as_mut ()); }
887
+ constexpr Once<T&> iter_mut () && noexcept
888
+ requires(std::is_reference_v<T>)
889
+ {
890
+ return Once<T&>::with (::sus::move (*this ).as_mut ());
891
+ }
868
892
869
893
constexpr Once<T> into_iter () && noexcept { return Once<T>::with (take ()); }
870
894
0 commit comments