either_stream.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. //
  2. // either_stream.hpp
  3. // optional.stream
  4. //
  5. // Created by Sam Jaffe on 1/28/17.
  6. //
  7. #pragma once
  8. #include <type_traits>
  9. #include <variant>
  10. template <typename T, typename E> using either = std::variant<T, E>;
  11. namespace stream {
  12. template <typename, typename> class either_stream;
  13. }
  14. namespace stream::traits {
  15. template <typename Either> struct either_traits {
  16. static constexpr bool const is_either = false;
  17. };
  18. template <typename T, typename E> struct either_traits<::either<T, E>> {
  19. static constexpr bool const is_either = true;
  20. using stream_type = either_stream<T, E>;
  21. using value_type = T;
  22. using error_type = E;
  23. };
  24. template <typename Either>
  25. using either_stream_t = typename either_traits<Either>::stream_type;
  26. template <typename Either>
  27. using either_value_t = typename either_traits<Either>::value_type;
  28. template <typename Either>
  29. inline constexpr bool is_either_v = either_traits<Either>::is_either;
  30. }
  31. namespace stream {
  32. template <typename T, typename E> class either_stream {
  33. private:
  34. template <typename F, typename T2 = T>
  35. using result_of = decltype(std::declval<F>()(std::declval<T2>()));
  36. private:
  37. ::either<T, E> value_;
  38. public:
  39. either_stream(E const & v) : value_(v) {}
  40. either_stream(E && v) : value_(std::forward<E>(v)) {}
  41. either_stream(T const & v) : value_(v) {}
  42. either_stream(T && v) : value_(std::forward<T>(v)) {}
  43. either_stream(::either<T, E> const & v) : value_(v) {}
  44. either_stream(::either<T, E> && v)
  45. : value_(std::forward<::either<T, E>>(v)) {}
  46. template <typename F>
  47. auto map(F && fun) const -> either_stream<result_of<F>, E> {
  48. static_assert(!traits::is_either_v<result_of<F>>, "Cannot nest eithers");
  49. if (value_.index() == 0) {
  50. return fun(std::get<0>(value_));
  51. } else {
  52. return std::get<1>(value_);
  53. }
  54. }
  55. template <typename F>
  56. auto flatmap(F && fun) const
  57. -> either_stream<traits::either_value_t<result_of<F>>, E> {
  58. if (value_.index() == 0) {
  59. return fun(std::get<0>(value_));
  60. } else {
  61. return std::get<1>(value_);
  62. }
  63. }
  64. template <typename FT, typename FE>
  65. auto match(FT && left, FE && right)
  66. -> std::common_type_t<result_of<FT, T>, result_of<FE, E>> {
  67. if (value_.index() == 0) {
  68. return left(std::get<0>(value_));
  69. } else {
  70. return right(std::get<1>(value_));
  71. }
  72. }
  73. };
  74. }
  75. namespace stream::either {
  76. /**
  77. * Construct a stream from the given type while explicitly providing both the
  78. * type and the error class
  79. */
  80. template <typename T, typename E>
  81. either_stream<T, E> make_stream(T const & opt) {
  82. return {{opt}};
  83. }
  84. /**
  85. * Construct a stream from the given type where the real type is an inferred
  86. * property
  87. */
  88. template <typename E, typename T>
  89. either_stream<T, E> make_stream(T const & opt) {
  90. return {{opt}};
  91. }
  92. /**
  93. * Construct a stream with the given either-type as a template parameter.
  94. */
  95. template <typename E>
  96. auto make_stream(traits::either_value_t<E> const & opt) {
  97. return traits::either_stream_t<E>{opt};
  98. }
  99. }