fork(1) download
  1. #include <functional>
  2.  
  3. template<typename Ret, typename ...Args>
  4. class stack_function_base {
  5. typedef stack_function_base<Ret, Args...> self_type;
  6. public:
  7. virtual Ret do_call(Args&& ...) = 0;
  8. virtual ~stack_function_base() {}
  9. virtual self_type* copy_to(void*) = 0;
  10. virtual self_type* move_to(void*) = 0;
  11. };
  12.  
  13. template<typename F, typename Ret, typename ...Args>
  14. class stack_function_impl : public stack_function_base<Ret, Args...>
  15. {
  16. typedef stack_function_base<Ret, Args...> base;
  17. public:
  18. stack_function_impl(F&& fn)
  19. : fn_(std::forward<F>(fn))
  20. {}
  21. Ret do_call(Args&& ... args) override final {
  22. return fn_(std::forward<Args>(args)...);
  23. }
  24. base* copy_to(void* addr) override final {
  25. return new (addr) stack_function_impl(*this);
  26. }
  27. base* move_to(void* addr) override final {
  28. return new (addr) stack_function_impl(std::move(*this));
  29. }
  30. private:
  31. F fn_;
  32. };
  33.  
  34. template<size_t MaxSize, typename Ret, typename ...Args>
  35. class stack_function
  36. {
  37. typedef stack_function_base<Ret, Args...> fn_interface;
  38. public:
  39. stack_function() : fn_(nullptr) {}
  40. stack_function(const stack_function& rhs) : fn_(0) {
  41. if(rhs.fn_)
  42. fn_ = rhs.fn_->copy_to(fn_storage_.data_);
  43. }
  44. stack_function( stack_function& rhs) : fn_(0) {
  45. if(rhs.fn_)
  46. fn_ = rhs.fn_->copy_to(fn_storage_.data_);
  47. }
  48. stack_function& operator =(const stack_function& rhs) {
  49. if(fn_) destroy_();
  50. if(rhs.fn_) fn_ = rhs.fn_->copy_to(fn_storage_.data_);
  51. }
  52. stack_function& operator =(stack_function& rhs) {
  53. if(fn_) destroy_();
  54. if(rhs.fn_) fn_ = rhs.fn_->copy_to(fn_storage_.data_);
  55. }
  56. stack_function(stack_function&& rhs) : fn_(nullptr) {
  57. if(rhs.fn_) fn_ = rhs.fn_->move_to(fn_storage_.data_);
  58. }
  59. stack_function& operator=(stack_function&& rhs) {
  60. if(fn_) destroy_();
  61. if(rhs.fn_) fn_ = rhs.fn_->move_to(fn_storage_.data_);
  62. }
  63. template<typename F>
  64. stack_function(F&& f) : fn_(0) {
  65. construct_(std::forward<F>(f));
  66. }
  67. template<typename F>
  68. void assign(F&& f) {
  69. if(fn_) destroy_();
  70. construct_(std::forward<F>(f));
  71. }
  72. ~stack_function() {
  73. if(fn_) destroy_();
  74. }
  75. operator bool() const {
  76. return fn_ != nullptr;
  77. }
  78. Ret operator()(Args&& ... args) {
  79. if(!fn_)
  80. throw std::bad_function_call();
  81. return fn_->do_call(std::forward<Args>(args)...);
  82. }
  83. private:
  84. void destroy_() {
  85. fn_->~fn_interface();
  86. fn_ = 0;
  87. }
  88. template<typename F>
  89. void construct_(F&& f) {
  90. typedef stack_function_impl<F, Ret, Args...> fn_type;
  91. static_assert(sizeof(fn_type) <= MaxSize
  92. , "non sufficient stack_function storage size");
  93. fn_ = new (fn_storage_.data_) fn_type(std::forward<F>(f));
  94. }
  95. private:
  96. fn_interface* fn_;
  97. union {
  98. long double align_;
  99. unsigned char data_[MaxSize];
  100. } fn_storage_;
  101. };
  102.  
  103. #include <iostream>
  104.  
  105. struct foo {
  106. foo() { std::cout << "foo constructor" << std::endl; }
  107. foo(const foo&) { std::cout << "foo copy constructor" << std::endl; }
  108. foo(foo&&) { std::cout << "foo move constructor" << std::endl; }
  109. void operator()() { std::cout << "foo call" << std::endl; }
  110. };
  111.  
  112. int main()
  113. {
  114. typedef stack_function<8, void> callback;
  115. callback c1 = foo();
  116. c1();
  117. callback c2 = std::move(c1);
  118. c2();
  119. callback c3 = c2;
  120. c3();
  121. return 0;
  122. }
Success #stdin #stdout 0s 3300KB
stdin
Standard input is empty
stdout
foo constructor
foo move constructor
foo call
foo move constructor
foo call
foo copy constructor
foo call