| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- //
- // optional_stream.hpp
- // optional.stream
- //
- // Created by Sam Jaffe on 1/28/17.
- //
- #pragma once
- #if __cplusplus > 201402L
- #include <optional>
- #else
- #include <experimental/optional>
- namespace std {
- using experimental::optional;
- using experimental::nullopt;
- }
- #endif
- namespace stream { namespace optional {
- namespace detail {
- template <typename T> struct flatmap_impl_t;
- template <typename T>
- struct flatmap_impl_t<std::optional<T>> { using type = T; };
-
- template <typename T>
- class optional_stream {
- private:
- template <typename F>
- using map_f = decltype(std::declval<F>()(std::declval<T>()));
- template <typename F>
- using flatmap_f = typename flatmap_impl_t<map_f<F>>::type;
- public:
- explicit optional_stream() : value(std::nullopt) {}
- explicit optional_stream(T const & v) : value(v) {}
- explicit optional_stream(T && v) : value(std::forward<T>(v)) {}
- explicit optional_stream(std::optional<T> const & v) : value(v) {}
- explicit optional_stream(std::optional<T> && v) : value(std::forward<std::optional<T>>(v)) {}
-
- operator std::optional<T>() const { return value; }
-
- template <typename F>
- optional_stream<map_f<F>> map(F && fun) const {
- using next_t = optional_stream<map_f<F>>;
- return !value ? next_t{} : next_t{fun(*value)};
- }
-
- template <typename F>
- optional_stream<flatmap_f<F>> flatmap(F && fun) const {
- using next_t = optional_stream<flatmap_f<F>>;
- return !value ? next_t{} : next_t{fun(*value)};
- }
- private:
- std::optional<T> value;
- };
- }
-
- template <typename T>
- auto make_stream(std::optional<T> const & opt) -> detail::optional_stream<T> {
- return detail::optional_stream<T>{opt};
- }
-
- template <typename T>
- auto make_stream(T const & val) -> detail::optional_stream<T> {
- return detail::optional_stream<T>{val};
- }
-
- template <typename T>
- auto make_stream() -> detail::optional_stream<T> {
- return detail::optional_stream<T>{};
- }
- } }
|