General Purpose library for Freestanding C++ and POSIX systems
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

139 Zeilen
2.2 KiB

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