General Purpose library for Freestanding C++ and POSIX systems
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.

143 lines
2.3 KiB

4 years ago
4 years ago
4 years ago
  1. #pragma once
  2. #include "gp/exception.hpp"
  3. namespace gp{
  4. template <typename>
  5. class function;
  6. template <typename ret, typename ...args>
  7. class function<ret(args...)>{
  8. struct virtual_callable
  9. {
  10. virtual ~virtual_callable() = default;
  11. virtual ret operator() (args...) = 0;
  12. };
  13. template<typename fn>
  14. class callable : public virtual_callable{
  15. fn internal_representation;
  16. public:
  17. callable(const fn& func)
  18. : internal_representation{func}
  19. {}
  20. virtual ~callable() override = default;
  21. ret operator() (args... arg_list) override
  22. {
  23. return internal_representation(arg_list...);
  24. }
  25. };
  26. enum state_t : uint8_t{
  27. INACTIVE = 0,
  28. ACTIVE = 1,
  29. NO_SOO = 0,
  30. SOO = 2
  31. };
  32. state_t state{};
  33. union{
  34. virtual_callable* functor = nullptr;
  35. char inplace[12];
  36. } self;
  37. public:
  38. template <typename T>
  39. function& operator=(T& t)
  40. {
  41. if(state & ACTIVE)
  42. {
  43. if(state & SOO)
  44. {
  45. ((virtual_callable*)&self)->~virtual_callable();
  46. }
  47. else
  48. {
  49. delete self.functor;
  50. }
  51. }
  52. if constexpr (sizeof(callable<T>) <= sizeof(self))
  53. {
  54. new((void*)&self) callable(t);
  55. state = (state_t)(ACTIVE | SOO);
  56. }
  57. else
  58. {
  59. self = new callable(t);
  60. state = (state_t)(ACTIVE | NO_SOO);
  61. }
  62. }
  63. function()
  64. {
  65. state = INACTIVE;
  66. }
  67. template <typename T>
  68. function(T t)
  69. {
  70. if constexpr (sizeof(callable<T>) <= sizeof(self))
  71. {
  72. new((void*)&self) callable<T>(t);
  73. state = (state_t)(ACTIVE | SOO);
  74. }
  75. else
  76. {
  77. self = new callable<T>(t);
  78. state = (state_t)(ACTIVE | NO_SOO);
  79. }
  80. }
  81. template <typename T>
  82. function(T& t)
  83. {
  84. if constexpr (sizeof(callable<T>) <= sizeof(self))
  85. {
  86. new((void*)&self) callable<T>(t);
  87. state = (state_t)(ACTIVE | SOO);
  88. }
  89. else
  90. {
  91. self.functor = new callable<T>(t);
  92. state = (state_t)(ACTIVE | NO_SOO);
  93. }
  94. }
  95. ret operator()(args... arg_list) const {
  96. if constexpr (gp_config::has_exceptions)
  97. {
  98. if(!(state & ACTIVE))
  99. {
  100. throw bad_functor{};
  101. }
  102. }
  103. if(state & SOO)
  104. {
  105. return (*(virtual_callable*)&self)(arg_list...);
  106. }
  107. else
  108. {
  109. return (*(self.functor))(arg_list...);
  110. }
  111. }
  112. ~function()
  113. {
  114. if(state & ACTIVE)
  115. {
  116. if(state & SOO)
  117. {
  118. ((virtual_callable*)&self)->~virtual_callable();
  119. }
  120. else
  121. {
  122. delete self.functor;
  123. }
  124. }
  125. }
  126. };
  127. }