function.hpp 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #pragma once
  2. #include <types/cplusplus.hpp>
  3. namespace std {
  4. namespace __inner {
  5. template <typename Ret, typename... Args>
  6. class _function_base {
  7. public:
  8. constexpr _function_base() = default;
  9. virtual constexpr ~_function_base() = default;
  10. virtual constexpr Ret operator()(Args&&... args) const = 0;
  11. };
  12. template <typename FuncLike, typename Ret, typename... Args>
  13. class _function : public _function_base<Ret, Args...> {
  14. private:
  15. FuncLike func;
  16. public:
  17. constexpr _function(FuncLike&& _func)
  18. : func(std::forward<FuncLike>(_func))
  19. {
  20. }
  21. constexpr ~_function() = default;
  22. constexpr Ret operator()(Args&&... args) const override
  23. {
  24. return func(std::forward<Args>(args)...);
  25. }
  26. };
  27. } // namespace __inner
  28. template <typename>
  29. class function;
  30. template <typename Ret, typename... Args>
  31. class function<Ret(Args...)> {
  32. private:
  33. char _data[sizeof(void*) * 2];
  34. using fb_t = __inner::_function_base<Ret, Args...>;
  35. constexpr fb_t* _f(void) const
  36. {
  37. return (fb_t*)_data;
  38. }
  39. public:
  40. template <typename FuncLike>
  41. constexpr function(FuncLike&& func)
  42. {
  43. static_assert(sizeof(FuncLike) <= sizeof(_data));
  44. new (_f()) __inner::_function<FuncLike, Ret, Args...>(std::forward<FuncLike>(func));
  45. }
  46. template <typename FuncPtr>
  47. constexpr function(FuncPtr* funcPtr)
  48. {
  49. new (_f()) __inner::_function<typename types::traits::decay<FuncPtr>::type, Ret, Args...>(
  50. std::forward<typename types::traits::decay<FuncPtr>::type>(funcPtr));
  51. }
  52. constexpr ~function()
  53. {
  54. _f()->~_function_base();
  55. }
  56. constexpr Ret operator()(Args... args) const
  57. {
  58. return (*_f())(std::forward<Args>(args)...);
  59. }
  60. };
  61. } // namespace std