after_next.h 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #pragma once
  8. #include <rpl/producer.h>
  9. namespace rpl {
  10. namespace details {
  11. template <typename SideEffect>
  12. class after_next_helper {
  13. public:
  14. template <typename OtherSideEffect>
  15. after_next_helper(OtherSideEffect &&method)
  16. : _method(std::forward<OtherSideEffect>(method)) {
  17. }
  18. template <typename Value, typename Error, typename Generator>
  19. auto operator()(producer<Value, Error, Generator> &&initial) {
  20. return make_producer<Value, Error>([
  21. initial = std::move(initial),
  22. method = std::move(_method)
  23. ](const auto &consumer) mutable {
  24. return std::move(initial).start(
  25. [method = std::move(method), consumer](auto &&value) {
  26. auto copy = method;
  27. consumer.put_next_copy(value);
  28. details::callable_invoke(
  29. std::move(copy),
  30. std::forward<decltype(value)>(value));
  31. }, [consumer](auto &&error) {
  32. consumer.put_error_forward(
  33. std::forward<decltype(error)>(error));
  34. }, [consumer] {
  35. consumer.put_done();
  36. });
  37. });
  38. }
  39. private:
  40. SideEffect _method;
  41. };
  42. } // namespace details
  43. template <typename SideEffect>
  44. inline auto after_next(SideEffect &&method)
  45. -> details::after_next_helper<std::decay_t<SideEffect>> {
  46. return details::after_next_helper<std::decay_t<SideEffect>>(
  47. std::forward<SideEffect>(method));
  48. }
  49. } // namespace rpl