make_stream.hpp 2.1 KB

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