diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-11-02 20:08:07 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-12-20 15:35:58 +0100 |
commit | 7e8e2ef0be2eebc7f872ea37620dc1b60d62197f (patch) | |
tree | 850b4a6656e976fd2dd91f5b3624ce29d3653b71 /asl/option.hpp | |
parent | c09323804c6c6d42c052b1c60061134261e515fc (diff) |
Add option::and_then
Diffstat (limited to 'asl/option.hpp')
-rw-r--r-- | asl/option.hpp | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/asl/option.hpp b/asl/option.hpp index ab88992..ebb9eef 100644 --- a/asl/option.hpp +++ b/asl/option.hpp @@ -3,6 +3,7 @@ #include "asl/assert.hpp"
#include "asl/meta.hpp"
#include "asl/maybe_uninit.hpp"
+#include "asl/functional.hpp"
namespace asl
{
@@ -334,7 +335,6 @@ public: constexpr bool has_value() const { return m_has_value; }
- // @Todo Do we want this on rvalues? Or maybe some kind of unwrap?
constexpr T&& value() &&
{
ASL_ASSERT(m_has_value); // @Todo Release assert
@@ -389,13 +389,46 @@ public: }
template<typename... Args>
- T& emplace(Args&&... args) &
+ constexpr T& emplace(Args&&... args) &
requires constructible<T, Args&&...>
{
if (m_has_value) { reset(); }
construct(ASL_FWD(args)...);
return value();
}
+
+ template<typename F>
+ constexpr auto and_then(F&& f) &
+ requires is_option<result_of_t<F(T&)>>
+ {
+ if (has_value())
+ {
+ return invoke(ASL_FWD(f), value());
+ }
+ return un_cvref_t<result_of_t<F(T&)>>{};
+ }
+
+ template<typename F>
+ constexpr auto and_then(F&& f) const&
+ requires is_option<result_of_t<F(const T&)>>
+ {
+ if (has_value())
+ {
+ return invoke(ASL_FWD(f), value());
+ }
+ return un_cvref_t<result_of_t<F(const T&)>>{};
+ }
+
+ template<typename F>
+ constexpr auto and_then(F&& f) &&
+ requires is_option<result_of_t<F(T)>>
+ {
+ if (has_value())
+ {
+ return invoke(ASL_FWD(f), ASL_MOVE(value()));
+ }
+ return un_cvref_t<result_of_t<F(T)>>{};
+ }
};
template<typename T>
|