make_stream.hpp 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #pragma once
  2. #include "source.hpp"
  3. namespace stream {
  4. /**
  5. * Construct a stream out of the given container. If C && is an rvalue
  6. * reference, the returned object will take ownership of cont. Otherwise, we
  7. * capture cont by reference to maximise performance.
  8. */
  9. template <typename C>
  10. auto make_stream(C && cont) -> detail::stream_base<decltype(*cont.begin())> {
  11. return std::make_shared<detail::source_stream<C>>(std::forward<C>(cont));
  12. }
  13. template <typename T>
  14. detail::stream_base<T&> make_empty_stream() {
  15. return std::make_shared<detail::range_stream<T*, T&>>(nullptr, nullptr);
  16. }
  17. /**
  18. * Construct a single element stream containing the pointer given
  19. */
  20. template <typename T> detail::stream_base<T &> make_stream(T * ptr) {
  21. return std::make_shared<detail::range_stream<T *, T &>>(ptr, ptr + 1);
  22. }
  23. /**
  24. * Construct a stream from input iterators representing the start and end
  25. * Requirements: It must be an iterator type that provides the trait
  26. * 'reference'
  27. */
  28. template <typename It>
  29. detail::stream_base<typename It::reference> make_stream(It begin, It end) {
  30. return std::make_shared<detail::range_stream<It>>(begin, end);
  31. }
  32. /**
  33. * Construct a stream given certain start and end bounds.
  34. * e.g. stream::make_range_stream(0, 10)
  35. */
  36. template <typename T>
  37. detail::stream_base<T &> make_range_stream(T start, T const & end) {
  38. std::vector<T> vec;
  39. vec.reserve(end - start);
  40. while (start < end) {
  41. vec.emplace_back(start++);
  42. }
  43. return make_stream(std::move(vec));
  44. }
  45. /**
  46. * Construct a stream given certain start and end bounds, as well as an
  47. * increment amount. e.g. stream::make_range_stream(0, 10, 2)
  48. */
  49. template <typename T>
  50. detail::stream_base<T &> make_range_stream(T start, T const & end,
  51. T const & increment) {
  52. int elems{(end - start) / increment};
  53. if (elems < 0 || end == start) { return {}; }
  54. std::vector<T> vec{start};
  55. vec.reserve(elems + 1);
  56. while (elems-- > 0) {
  57. vec.emplace_back(start += increment);
  58. }
  59. return make_stream(std::move(vec));
  60. }
  61. }