Advertisement
Guest User

Untitled

a guest
Jan 20th, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.24 KB | None | 0 0
  1. #ifndef FUNCTION_FUNCTION_H
  2. #define FUNCTION_FUNCTION_H
  3.  
  4. #include <utility>
  5. #include <variant>
  6. #include <memory>
  7.  
  8. static const size_t B_SIZE = 64;
  9.  
  10.  
  11. template <typename T>
  12. class function;
  13.  
  14. template <typename Ret, typename ...Args>
  15. class function<Ret (Args...)> {
  16. public:
  17. Ret operator()(Args...args) const {
  18. if (!is_small)
  19. return holder->invoke(std::forward<Args>(args)...);
  20. return ((function_holder_base *)buf)->invoke(std::forward<Args>(args)...);
  21. }
  22.  
  23. function() noexcept : holder(nullptr), is_small(false) {}
  24.  
  25. function(std::nullptr_t) noexcept : holder(nullptr), is_small(false) {}
  26.  
  27. function(const function &other) {
  28. function_holder_base *c = (function_holder_base *) other.buf;
  29. is_small = other.is_small;
  30. if (other.is_small)
  31. c->create_small_copy(buf);
  32. else
  33. holder = other.holder->copy();
  34.  
  35. }
  36.  
  37. function(function &&other) noexcept : holder(nullptr){
  38. std::swap(buf, other.buf);
  39. std::swap(is_small, other.is_small);
  40. other.is_small = false;
  41. }
  42.  
  43. function& operator=(const function& other) {
  44. function tmp(other);
  45. swap(tmp);
  46. return *this;
  47. }
  48.  
  49. function &operator=(function &&other) noexcept {
  50. auto tmp(std::forward<function>(other));
  51. swap(tmp);
  52. return *this;
  53. }
  54.  
  55. void swap(function& other) noexcept {
  56. std::swap(buf, other.buf);
  57. std::swap(is_small, other.is_small);
  58. }
  59.  
  60. explicit operator bool() const noexcept {
  61. if (is_small)
  62. return true;
  63. return static_cast<bool>(holder);
  64. }
  65.  
  66.  
  67. template<typename T>
  68. function(T t) {
  69. if constexpr (sizeof(function_holder<T>(t)) <= B_SIZE){
  70. is_small = true;
  71. new(buf) function_holder<T>(std::move(t));
  72. }
  73. else{
  74. is_small = false;
  75. new(buf) std::unique_ptr<function_holder < T>>(std::make_unique<function_holder<T>>(std::move(t)));
  76. }
  77. }
  78.  
  79. ~function() {
  80. if (is_small) {
  81. ((function_holder_base*)buf)->~function_holder_base();
  82. } else {
  83. holder.reset();
  84. }
  85. }
  86.  
  87.  
  88.  
  89. class function_holder_base {
  90. public:
  91. function_holder_base() {};
  92. virtual ~function_holder_base() {};
  93. virtual Ret invoke(Args...) = 0;
  94. virtual std::unique_ptr<function_holder_base> copy() const = 0;
  95. virtual void create_small_copy(void *adr) = 0;
  96.  
  97. };
  98.  
  99. template <typename Func>
  100. class function_holder : public function_holder_base {
  101. public:
  102. function_holder(const Func& func) : f(func) {}
  103.  
  104. ~function_holder() override = default;
  105.  
  106. Ret invoke(Args...args){
  107. return f(std::forward<Args>(args)...);
  108. }
  109.  
  110. void create_small_copy(void *adr){
  111. new (adr) function_holder<Func>(f);
  112.  
  113. }
  114.  
  115. std::unique_ptr<function_holder_base> copy() const override {
  116. return std::make_unique<function_holder<Func>>(f);
  117. }
  118.  
  119. Func f;
  120.  
  121. };
  122.  
  123. private:
  124. union {
  125. std::unique_ptr<function_holder_base> holder;
  126. char buf[B_SIZE];
  127. };
  128. bool is_small;
  129. };
  130.  
  131. #endif /
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement