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.

59 lines
1.5 KiB

  1. #pragma once
  2. #include <utility>
  3. #include <cpputils/mp/misc/when.h>
  4. #include <cpputils/mp/misc/tag_of.h>
  5. #include <cpputils/mp/misc/default.h>
  6. namespace utl {
  7. namespace mp {
  8. namespace __impl
  9. {
  10. struct eval_t
  11. {
  12. template <typename Expr>
  13. constexpr auto operator()(Expr&& expr) const;
  14. };
  15. }
  16. constexpr __impl::eval_t eval { };
  17. namespace __impl
  18. {
  19. template <typename T, typename = void>
  20. struct eval_impl
  21. : eval_impl<T, when<true>>
  22. { };
  23. template <typename T, bool condition>
  24. struct eval_impl<T, when<condition>>
  25. : default_
  26. {
  27. template <typename Expr>
  28. static constexpr auto eval_helper(Expr&& expr, int)
  29. { return static_cast<Expr&&>(expr)(); }
  30. template <typename Expr>
  31. static constexpr auto eval_helper(Expr&&, ...)
  32. {
  33. static_assert(wrong<Expr> { },
  34. "eval(expr) requires the expression to be a a nullary Callable");
  35. }
  36. template <typename Expr>
  37. static constexpr decltype(auto) apply(Expr&& expr)
  38. { return eval_helper(static_cast<Expr&&>(expr), int { }); }
  39. };
  40. template <typename Expr>
  41. constexpr auto eval_t::operator()(Expr&& expr) const
  42. {
  43. using tag_type = tag_of<Expr>;
  44. using eval_impl_type = eval_impl<tag_type>;
  45. return eval_impl_type::apply(std::forward<Expr>(expr));;
  46. }
  47. }
  48. }
  49. }