[libcxx-commits] [PATCH] D113408: [libc++] Implement P0798R8 (Monadic operations for std::optional)

Louis Dionne via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Wed Dec 8 14:05:57 PST 2021


ldionne requested changes to this revision.
ldionne added a comment.
This revision now requires changes to proceed.

Almost LGTM, thanks for working on this!



================
Comment at: libcxx/include/optional:135-145
+    // [optional.monadic], monadic operations
+    template<class F> constexpr auto and_then(F&& f) &;         // since c++23
+    template<class F> constexpr auto and_then(F&& f) &&;        // since c++23
+    template<class F> constexpr auto and_then(F&& f) const&;    // since c++23
+    template<class F> constexpr auto and_then(F&& f) const&&;   // since c++23
+    template<class F> constexpr auto transform(F&& f) &;        // since c++23
+    template<class F> constexpr auto transform(F&& f) &&;       // since c++23
----------------



================
Comment at: libcxx/include/optional:616
 
+#if _LIBCPP_STD_VER > 20
+template<class _Tp>
----------------
I think it is fine to unconditionally define this template. We'll only be using it in C++20, but I don't think it's worth the complexity to add the `#if`.


================
Comment at: libcxx/include/optional:1060
+    using _Up = invoke_result_t<_Func, const value_type&>;
+    static_assert(__is_std_optional<_Up>::value,
+                  "Result of f(value()) must be a specialization of std::optional<T>");
----------------
The spec says:

> Let `U` be `invoke_result_t<F, decltype(std::move(value()))>`.
> Mandates: `remove_cvref_t<U>` is a specialization of `optional`.

I think we should be checking this instead:

```
static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, ...);
```

This comment probably applies elsewhere.


================
Comment at: libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp:25-32
+template <class O, class F>
+requires requires(O&& o, F&& f) { {std::forward<O>(o).or_else(std::forward<F>(f))}; }
+constexpr bool has_or_else(O&&, F&&) { return true; }
+
+template <class O, class F>
+constexpr bool has_or_else(O&&, F&&) {
+  return false;
----------------
I believe this would work and be equivalent:

```
template <class Opt, class F>
concept has_or_else = requires(Opt&& opt, F&& f) {
  { std::forward<Opt>(opt).or_else(std::forward<F>(f)) };
};
```


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D113408/new/

https://reviews.llvm.org/D113408



More information about the libcxx-commits mailing list