function.hpp 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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(types::forward<FuncLike>(_func))
  19. {
  20. }
  21. constexpr ~_function() = default;
  22. constexpr Ret operator()(Args&&... args) const override
  23. {
  24. return func(types::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*) * 4];
  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. using underlying_function_type = __inner::_function<FuncLike, Ret, Args...>;
  44. static_assert(sizeof(underlying_function_type) <= sizeof(_data), "Too large FuncLike object");
  45. new (_f()) underlying_function_type(types::forward<FuncLike>(func));
  46. }
  47. template <typename FuncPtr>
  48. constexpr function(FuncPtr* funcPtr)
  49. {
  50. new (_f()) __inner::_function<typename types::traits::decay<FuncPtr>::type, Ret, Args...>(
  51. types::forward<typename types::traits::decay<FuncPtr>::type>(funcPtr));
  52. }
  53. constexpr ~function()
  54. {
  55. _f()->~_function_base();
  56. }
  57. constexpr Ret operator()(Args... args) const
  58. {
  59. return (*_f())(types::forward<Args>(args)...);
  60. }
  61. };
  62. } // namespace std