#pragma once #include #include namespace hr { template class function; template struct function_state_base { virtual R call(Args...) const = 0; virtual function_state_base *clone() const = 0; virtual ~function_state_base() {} }; template struct function_state : function_state_base { T t_; explicit function_state(T t) : t_(std::move(t)) {} R call(Args... args) const override { return const_cast(t_)(static_cast(args)...); } function_state_base *clone() const override { return new function_state(*this); } }; template class function { function_state_base *ptr_; public: function() : ptr_(nullptr) {} template::type>()(std::declval()...)))> function(Callable&& t) : ptr_(new function_state::type, R, Args...>(static_cast(t))) {} ~function() { delete ptr_; } function(function& rhs) : ptr_(rhs.ptr_ ? rhs.ptr_->clone() : nullptr) {} function(const function& rhs) : ptr_(rhs.ptr_ ? rhs.ptr_->clone() : nullptr) {} function(function&& rhs) noexcept : ptr_(rhs.ptr_) { rhs.ptr_ = nullptr; } function(const function&& rhs) = delete; void operator=(function rhs) noexcept { std::swap(ptr_, rhs.ptr_); } R operator()(Args... args) const { return ptr_->call(static_cast(args)...); } explicit operator bool() const noexcept { return ptr_ != nullptr; } template T* target() { auto ptr = dynamic_cast*> (ptr_); if(!ptr) return nullptr; return &ptr->t_; } }; } // namespace hr