either_stream.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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. template <typename T, typename E> struct either_traits<::either<T, E>> {
  17. using stream_type = either_stream<T, E>;
  18. using value_type = T;
  19. using error_type = E;
  20. };
  21. template <typename Either>
  22. using either_stream_t = typename either_traits<Either>::stream_type;
  23. template <typename Either>
  24. using either_value_t = typename either_traits<Either>::value_type;
  25. }
  26. namespace stream {
  27. template <typename T, typename E> class either_stream {
  28. private:
  29. template <typename F, typename T2 = T>
  30. using map_f = decltype(std::declval<F>()(std::declval<T2>()));
  31. template <typename F, typename T2 = T>
  32. using flatmap_f = traits::either_value_t<map_f<F, T2>>;
  33. template <typename FT, typename FE>
  34. inline static constexpr bool is_consumer_v =
  35. std::is_void_v<map_f<FT, T>> && std::is_void_v<map_f<FE, E>>;
  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> either_stream<map_f<F>, E> map(F && fun) const {
  47. if (value_.index() == 0) {
  48. return fun(std::get<0>(value_));
  49. } else {
  50. return std::get<1>(value_);
  51. }
  52. }
  53. template <typename F>
  54. either_stream<flatmap_f<F>, E> flatmap(F && fun) const {
  55. if (value_.index() == 0) {
  56. return fun(std::get<0>(value_));
  57. } else {
  58. return std::get<1>(value_);
  59. }
  60. }
  61. template <typename FT, typename FE>
  62. auto match(FT && left, FE && right)
  63. -> std::common_type_t<map_f<FT, T>, map_f<FE, E>> {
  64. if (value_.index() == 0) {
  65. return left(std::get<0>(value_));
  66. } else {
  67. return right(std::get<1>(value_));
  68. }
  69. }
  70. ::either<T, E> const & value() const { return value_; }
  71. };
  72. }
  73. namespace stream::either {
  74. /**
  75. * Construct a stream from the given type while explicitly providing both the
  76. * type and the error class
  77. */
  78. template <typename T, typename E>
  79. either_stream<T, E> make_stream(T const & opt) {
  80. return {{opt}};
  81. }
  82. /**
  83. * Construct a stream from the given type where the real type is an inferred
  84. * property
  85. */
  86. template <typename E, typename T>
  87. either_stream<T, E> make_stream(T const & opt) {
  88. return {{opt}};
  89. }
  90. /**
  91. * Construct a stream with the given either-type as a template parameter.
  92. */
  93. template <typename E>
  94. auto make_stream(traits::either_value_t<E> const & opt) {
  95. return traits::either_stream_t<E>{opt};
  96. }
  97. }