common_view.h 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. //
  2. // common_view.h
  3. // stream
  4. //
  5. // Created by Sam Jaffe on 3/30/23.
  6. //
  7. #pragma once
  8. #include <iterator/proxy.h>
  9. #include <stream/detail/traits.h>
  10. #include <stream/forward.h>
  11. #include <iterator/detail/macro.h>
  12. #define FWD(x) std::forward<decltype(x)>(x)
  13. namespace stream::ranges {
  14. template <typename It, typename S>
  15. class common_iterator : public proxy<It, common_iterator<It, S>> {
  16. public:
  17. static_assert(!std::is_same_v<It, S>, "cannot operator on common types");
  18. using super_t = proxy<It, common_iterator<It, S>>;
  19. using sentinel_type = common_iterator;
  20. public:
  21. using super_t::super_t;
  22. common_iterator(S) : super_t() {}
  23. bool equal_to(common_iterator const & other) const {
  24. return (at_end() && other.at_end()) || super_t::impl() == other.impl();
  25. }
  26. bool at_end() const { return super_t::impl() == S(); }
  27. };
  28. template <typename S> class common_view {
  29. private:
  30. using iterator = common_iterator<detail::begin_t<S>, detail::end_t<S>>;
  31. private:
  32. S stream_;
  33. public:
  34. common_view(S && stream) : stream_(FWD(stream)) {}
  35. auto begin() const { return iterator(stream_.begin()); }
  36. auto end() const { return iterator(stream_.end()); }
  37. SFINAE(detail::has_empty_v<S>, bool) empty() const { return stream_.empty(); }
  38. SFINAE(detail::has_size_v<S>, bool) size() const { return stream_.size(); }
  39. };
  40. template <typename S> common_view(S &&) -> common_view<S>;
  41. }
  42. namespace stream::ranges::views {
  43. struct common {
  44. template <typename Stream> friend auto operator|(Stream && stream, common) {
  45. if constexpr (detail::is_sentinal_v<Stream>) {
  46. return common_view(FWD(stream));
  47. } else {
  48. return FWD(stream);
  49. }
  50. }
  51. };
  52. }
  53. MAKE_ITERATOR_FACADE_TYPEDEFS_T(stream::ranges::common_iterator);
  54. #undef FWD
  55. #include <iterator/detail/undef.h>