You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

68 lines
1.9 KiB

  1. #pragma once
  2. #include <cpputils/mp/misc/when.h>
  3. #include <cpputils/mp/misc/make.h>
  4. #include <cpputils/mp/misc/tag_of.h>
  5. #include <cpputils/mp/misc/default.h>
  6. #include <cpputils/mp/operations/unpack.h>
  7. namespace utl {
  8. namespace mp {
  9. namespace __impl
  10. {
  11. struct transform_t
  12. {
  13. template<typename Xs, typename F>
  14. constexpr auto operator()(Xs&& xs, F&& f) const;
  15. };
  16. }
  17. constexpr __impl::transform_t transform { };
  18. namespace __impl
  19. {
  20. template<typename Xs, typename = void>
  21. struct transform_impl
  22. : transform_impl<Xs, when<true>>
  23. { };
  24. template<typename T, bool condition>
  25. struct transform_impl<T, when<condition>>
  26. : default_
  27. {
  28. template<typename Xs, typename F>
  29. static constexpr auto apply(Xs&& xs, F&& f) = delete;
  30. };
  31. template<typename T>
  32. struct transform_impl<T, when<!is_default<unpack_impl<tag_of<T>>>::value>>
  33. {
  34. using tag_type = tag_of<T>;
  35. template<typename F>
  36. struct transformer
  37. {
  38. F f;
  39. template<typename... Xn>
  40. constexpr auto operator()(Xn&&... xn) const
  41. { return make<tag_type>((*f)(std::forward<Xn>(xn))...); }
  42. };
  43. template<typename Xs, typename F>
  44. static constexpr auto apply(Xs&& xs, F&& f)
  45. { return unpack(std::forward<Xs>(xs), transformer<decltype(&f)> { &f }); }
  46. };
  47. template<typename Xs, typename F>
  48. constexpr auto transform_t::operator()(Xs&& xs, F&& f) const
  49. {
  50. using tag_type = tag_of<Xs>;
  51. using transform_impl_type = transform_impl<tag_type>;
  52. return transform_impl_type::apply(std::forward<Xs>(xs), std::forward<F>(f));
  53. }
  54. }
  55. }
  56. }