General Purpose library for Freestanding C++ and POSIX systems
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

144 righe
2.4 KiB

  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. // tweak a way to store a size in there for trivial copy
  27. enum state_t : uint8_t{
  28. INACTIVE = 0,
  29. ACTIVE = 1,
  30. NO_SOO = 0,
  31. SOO = 2
  32. };
  33. state_t state{};
  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.inplace)->~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.inplace) callable(t);
  56. state = (state_t)(ACTIVE | SOO);
  57. }
  58. else
  59. {
  60. self.functor = new callable<T>(t);
  61. state = (state_t)(ACTIVE | NO_SOO);
  62. }
  63. }
  64. function()
  65. {
  66. state = INACTIVE;
  67. }
  68. template <typename T>
  69. function(T t)
  70. {
  71. if constexpr (sizeof(callable<T>) <= sizeof(self))
  72. {
  73. new((void*)self.inplace) callable<T>(t);
  74. state = (state_t)(ACTIVE | SOO);
  75. }
  76. else
  77. {
  78. self.functor = new callable<T>(t);
  79. state = (state_t)(ACTIVE | NO_SOO);
  80. }
  81. }
  82. template <typename T>
  83. function(T& t)
  84. {
  85. if constexpr (sizeof(callable<T>) <= sizeof(self))
  86. {
  87. new((void*)&self) callable<T>(t);
  88. state = (state_t)(ACTIVE | SOO);
  89. }
  90. else
  91. {
  92. self.functor = new callable<T>(t);
  93. state = (state_t)(ACTIVE | NO_SOO);
  94. }
  95. }
  96. ret operator()(args... arg_list) const {
  97. if constexpr (gp_config::has_exceptions)
  98. {
  99. if(!(state & ACTIVE))
  100. {
  101. throw bad_functor{};
  102. }
  103. }
  104. if(state & SOO)
  105. {
  106. return (*(virtual_callable*)&self)(arg_list...);
  107. }
  108. else
  109. {
  110. return (*self.functor)(arg_list...);
  111. }
  112. }
  113. ~function()
  114. {
  115. if(state & ACTIVE)
  116. {
  117. if(state & SOO)
  118. {
  119. ((virtual_callable*)&self)->~virtual_callable();
  120. }
  121. else
  122. {
  123. delete self.functor;
  124. }
  125. }
  126. }
  127. };
  128. }