Advertisement
NLinker

Maybe monad in C++

Jan 16th, 2018
237
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.19 KB | None | 0 0
  1. // http://govnokod.ru/23568
  2.  
  3. #include <experimental/coroutine>
  4. #include <iostream>
  5. #include <optional>
  6. #include <utility>
  7.  
  8. template<typename T>
  9. class Maybe
  10. {
  11.     std::shared_ptr<std::optional<T>> m_maybe = std::make_shared<std::optional<T>>();
  12. public:
  13.     Maybe() = default;
  14.    
  15.     Maybe(const T& t)
  16.     : m_maybe { std::make_shared<std::optional<T>>(t) }
  17.     {
  18.     }
  19.  
  20.     explicit operator bool() const { return static_cast<bool>(*m_maybe); }
  21.     T& operator* () { return **m_maybe; }
  22.     const T& operator*() const { return **m_maybe; }
  23.    
  24.     void reset() { m_maybe->reset(); }
  25.    
  26.     template<typename U>
  27.     void emplace(U&& u) { m_maybe->emplace(std::forward<U>(u)); }
  28. };
  29.  
  30. template<typename T>
  31. void printMaybe(const Maybe<T>& opt)
  32. {
  33.     if (opt)
  34.         std::cout << *opt << std::endl;
  35.     else
  36.         std::cout << "<empty>" << std::endl;
  37. }
  38.  
  39. template<typename T, typename... Args>
  40. struct std::experimental::coroutine_traits<Maybe<T>, Args...>
  41. {
  42.     struct promise_type
  43.     {
  44.         Maybe<T> m_maybe;
  45.        
  46.         auto get_return_object() { return m_maybe; }
  47.        
  48.         std::experimental::suspend_never initial_suspend() { return {}; }
  49.         std::experimental::suspend_never final_suspend() { return {}; }
  50.        
  51.         void unhandled_exception() { m_maybe.reset(); }
  52.        
  53.         template<typename U>
  54.         void return_value(U&& u) { m_maybe.emplace(std::forward<U>(u)); }
  55.     };
  56. };
  57.  
  58. template<typename T>
  59. auto operator co_await(const Maybe<T>& maybe)
  60. {
  61.     struct Awaiter
  62.     {
  63.         const Maybe<T>& input;
  64.  
  65.         bool await_ready() { return static_cast<bool>(input); }
  66.         auto await_resume() { return *input; }
  67.         void await_suspend(std::experimental::coroutine_handle<> coro) { coro.destroy(); }
  68.     };
  69.  
  70.     return Awaiter { maybe };
  71. }
  72.  
  73. Maybe<int> maybeAdd(const Maybe<int>& maybeA, const Maybe<int>& maybeB)
  74. {
  75.     auto a = co_await maybeA;
  76.     auto b = co_await maybeB;
  77.     co_return a + b;
  78. }
  79.  
  80. int main()
  81. {
  82.   /*
  83.     printMaybe(maybeAdd({ 1 }, { 2 }));
  84.     printMaybe(maybeAdd({}, { 2 }));
  85.     printMaybe(maybeAdd({ 1 }, {}));
  86.     */
  87.     const auto res = maybeAdd({ 1 }, { 2 });
  88.     return res ? *res : 0;
  89. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement