#pragma once #include "gp/exception.hpp" namespace gp{ template class function; template class function{ struct virtual_callable { virtual ~virtual_callable() = default; virtual ret operator() (args...) = 0; }; template class callable : public virtual_callable{ fn internal_representation; public: callable(const fn& func) : internal_representation{func} {} virtual ~callable() override = default; ret operator() (args... arg_list) override { return internal_representation(arg_list...); } }; // tweak a way to store a size in there for trivial copy enum state_t : uint8_t{ INACTIVE = 0, ACTIVE = 1, NO_SOO = 0, SOO = 2 }; state_t state{}; union{ virtual_callable* functor = nullptr; char inplace[12]; } self; public: template function& operator=(T& t) { if(state & ACTIVE) { if(state & SOO) { ((virtual_callable*)self.inplace)->~virtual_callable(); } else { delete self.functor; } } if constexpr (sizeof(callable) <= sizeof(self)) { new((void*)self.inplace) callable(t); state = (state_t)(ACTIVE | SOO); } else { self.functor = new callable(t); state = (state_t)(ACTIVE | NO_SOO); } } function() { state = INACTIVE; } template function(T t) { if constexpr (sizeof(callable) <= sizeof(self)) { new((void*)self.inplace) callable(t); state = (state_t)(ACTIVE | SOO); } else { self.functor = new callable(t); state = (state_t)(ACTIVE | NO_SOO); } } template function(T& t) { if constexpr (sizeof(callable) <= sizeof(self)) { new((void*)&self) callable(t); state = (state_t)(ACTIVE | SOO); } else { self.functor = new callable(t); state = (state_t)(ACTIVE | NO_SOO); } } ret operator()(args... arg_list) const { if constexpr (gp_config::has_exceptions) { if(!(state & ACTIVE)) { throw bad_functor{}; } } if(state & SOO) { return (*(virtual_callable*)&self)(arg_list...); } else { return (*self.functor)(arg_list...); } } ~function() { if(state & ACTIVE) { if(state & SOO) { ((virtual_callable*)&self)->~virtual_callable(); } else { delete self.functor; } } } }; }