General Purpose library for Freestanding C++ and POSIX systems
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

138 linhas
2.2 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 : 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)
  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 = 0;
  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 = ACTIVE | SOO;
  56. }
  57. else
  58. {
  59. self = new callable(t);
  60. state = ACTIVE | NO_SOO;
  61. }
  62. }
  63. template <typename T>
  64. function(T t)
  65. {
  66. if constexpr (sizeof(callable<T>) <= sizeof(self))
  67. {
  68. new((void*)&self) callable(t);
  69. state = ACTIVE | SOO;
  70. }
  71. else
  72. {
  73. self = new callable(t);
  74. state = ACTIVE | NO_SOO;
  75. }
  76. }
  77. template <typename T>
  78. function(T& t)
  79. {
  80. if constexpr (sizeof(callable<T>) <= sizeof(self))
  81. {
  82. new((void*)&self) callable(t);
  83. state = ACTIVE | SOO;
  84. }
  85. else
  86. {
  87. self = new callable(t);
  88. state = ACTIVE | NO_SOO;
  89. }
  90. }
  91. ret operator()(args... arg_list) const {
  92. if constexpr (gp_config::has_exceptions)
  93. {
  94. if(!(state & ACTIVE))
  95. {
  96. throw bad_functor{};
  97. }
  98. }
  99. if(state & SOO)
  100. {
  101. return (*(virtual_callable*)&self)(arg_list...);
  102. }
  103. else
  104. {
  105. return (*(self.functor))(arg_list...);
  106. }
  107. }
  108. ~function()
  109. {
  110. if(state & ACTIVE)
  111. {
  112. if(state & SOO)
  113. {
  114. ((virtual_callable*)&self)->~virtual_callable();
  115. }
  116. else
  117. {
  118. delete self.functor;
  119. }
  120. }
  121. }
  122. };
  123. }