|
|
- #pragma once
- #include "gp/exception.hpp"
-
- namespace gp{
-
- template <typename>
- class function;
-
- template <typename ret, typename ...args>
- class function<ret(args...)>{
- struct virtual_callable
- {
- virtual ~virtual_callable() = default;
- virtual ret operator() (args...) = 0;
- };
-
- template<typename fn>
- 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 <typename T>
- function& operator=(T& t)
- {
- if(state & ACTIVE)
- {
- if(state & SOO)
- {
- ((virtual_callable*)self.inplace)->~virtual_callable();
- }
- else
- {
- delete self.functor;
- }
- }
- if constexpr (sizeof(callable<T>) <= sizeof(self))
- {
- new((void*)self.inplace) callable(t);
- state = (state_t)(ACTIVE | SOO);
- }
- else
- {
- self.functor = new callable<T>(t);
- state = (state_t)(ACTIVE | NO_SOO);
- }
- }
-
- function()
- {
- state = INACTIVE;
- }
-
- template <typename T>
- function(T t)
- {
- if constexpr (sizeof(callable<T>) <= sizeof(self))
- {
- new((void*)self.inplace) callable<T>(t);
- state = (state_t)(ACTIVE | SOO);
- }
- else
- {
- self.functor = new callable<T>(t);
- state = (state_t)(ACTIVE | NO_SOO);
- }
- }
-
- template <typename T>
- function(T& t)
- {
- if constexpr (sizeof(callable<T>) <= sizeof(self))
- {
- new((void*)&self) callable<T>(t);
- state = (state_t)(ACTIVE | SOO);
- }
- else
- {
- self.functor = new callable<T>(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;
- }
- }
-
- }
- };
-
- }
|