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.

80 lines
2.6 KiB

  1. #pragma once
  2. #include <cpputils/mp/misc/when.h>
  3. #include <cpputils/mp/misc/tag_of.h>
  4. #include <cpputils/mp/misc/default.h>
  5. #include <cpputils/mp/intern/has_value.h>
  6. #include <cpputils/mp/operations/if.fwd.h>
  7. #include <cpputils/mp/operations/eval.h>
  8. namespace utl {
  9. namespace mp {
  10. namespace __impl
  11. {
  12. struct eval_if_t
  13. {
  14. template <typename Cond, typename Then, typename Else>
  15. constexpr auto operator()(Cond&& c, Then&& t, Else&& e) const;
  16. };
  17. }
  18. constexpr __impl::eval_if_t eval_if { };
  19. namespace __impl
  20. {
  21. template <typename T, typename = void>
  22. struct eval_if_impl
  23. : eval_if_impl<T, when<true>>
  24. { };
  25. template <typename T, bool condition>
  26. struct eval_if_impl<T, when<condition>>
  27. : default_
  28. {
  29. template <typename ...Args>
  30. static constexpr auto apply(Args&& ...) = delete;
  31. };
  32. template <typename T>
  33. struct eval_if_impl<T, when<is_arithmetic<T>::value>>
  34. {
  35. template <typename Cond, typename Then, typename Else>
  36. static constexpr auto apply(const Cond& cond, Then&& t, Else&& e)
  37. {
  38. return cond ? eval(std::forward<Then>(t))
  39. : eval(std::forward<Else>(e));
  40. }
  41. };
  42. template <typename T>
  43. struct eval_if_impl<T, when<intern::has_value<T>::value>>
  44. {
  45. template<typename Then, typename Else>
  46. static constexpr auto eval_if_helper(c_true_t, Then&& t, Else&& e)
  47. { return eval(std::forward<Then>(t)); }
  48. template<typename Then, typename Else>
  49. static constexpr auto eval_if_helper(c_false_t, Then&& t, Else&& e)
  50. { return eval(std::forward<Else>(e)); }
  51. template <typename Cond, typename Then, typename Else>
  52. static constexpr auto apply(const Cond&, Then&& t, Else&& e)
  53. {
  54. constexpr auto cond = value<Cond>();
  55. constexpr bool truth_value = if_(cond, true, false);
  56. return eval_if_helper(c_bool_t<truth_value> { }, std::forward<Then>(t), std::forward<Else>(e));
  57. }
  58. };
  59. template <typename Cond, typename Then, typename Else>
  60. constexpr auto eval_if_t::operator()(Cond&& c, Then&& t, Else&& e) const
  61. {
  62. using tag_type = tag_of<Cond>;
  63. using eval_if_type = eval_if_impl<tag_type>;
  64. return eval_if_type::apply(std::forward<Cond>(c), std::forward<Then>(t), std::forward<Else>(e));
  65. }
  66. }
  67. }
  68. }