|
|
@ -1,6 +1,7 @@ |
|
|
|
#pragma once
|
|
|
|
#include "gp/exception.hpp"
|
|
|
|
#include "gp/algorithm/tmp_manip.hpp"
|
|
|
|
#include "gp/algorithm/move.hpp"
|
|
|
|
namespace gp{ |
|
|
|
|
|
|
|
template <typename> |
|
|
@ -10,21 +11,24 @@ namespace gp{ |
|
|
|
class function<ret(args...)>{ |
|
|
|
struct virtual_callable |
|
|
|
{ |
|
|
|
virtual void inplace_copy(char*) = 0; |
|
|
|
virtual void inplace_move(char*) = 0; |
|
|
|
virtual virtual_callable* all_copy() = 0; |
|
|
|
virtual void inplace_copy(char*) = 0; |
|
|
|
virtual virtual_callable* all_move() = 0; |
|
|
|
virtual ~virtual_callable() = default; |
|
|
|
virtual ret operator() (args...) = 0; |
|
|
|
}; |
|
|
|
|
|
|
|
template<typename fn> |
|
|
|
class callable : public virtual_callable{ |
|
|
|
fn internal_representation; |
|
|
|
class callable k">final : public virtual_callable{ |
|
|
|
k">typename gp::remove_reference<fn>::type internal_representation; |
|
|
|
public: |
|
|
|
callable(const fn& func) |
|
|
|
: internal_representation{func} |
|
|
|
callable(const fn func) |
|
|
|
: internal_representation{gp::move(func)} |
|
|
|
{} |
|
|
|
|
|
|
|
callable(callable&) = default; |
|
|
|
callable(callable&&) = default; |
|
|
|
|
|
|
|
virtual ~callable() override = default; |
|
|
|
|
|
|
@ -36,6 +40,14 @@ namespace gp{ |
|
|
|
return new callable(*this); |
|
|
|
} |
|
|
|
|
|
|
|
virtual void inplace_move(char* ptr) override { |
|
|
|
new(ptr) callable(gp::move(*this)); |
|
|
|
} |
|
|
|
|
|
|
|
virtual virtual_callable* all_move() override { |
|
|
|
return new callable(gp::move(*this)); |
|
|
|
} |
|
|
|
|
|
|
|
ret operator() (args... arg_list) override |
|
|
|
{ |
|
|
|
return internal_representation(arg_list...); |
|
|
@ -94,46 +106,59 @@ namespace gp{ |
|
|
|
} |
|
|
|
|
|
|
|
template <typename T> |
|
|
|
function(T t) |
|
|
|
functiono"><>(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<> |
|
|
|
function<function>(function& t) { |
|
|
|
if(t.state & SOO) |
|
|
|
{ |
|
|
|
t.self.functor->inplace_copy(self.inplace); |
|
|
|
state = (state_t)(ACTIVE | SOO); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
self.functor = t.self.functor->all_copy(); |
|
|
|
state = (state_t)(ACTIVE | NO_SOO); |
|
|
|
if constexpr (!std::is_same_v<T, function>) { |
|
|
|
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); |
|
|
|
} |
|
|
|
} else { |
|
|
|
if(t.state & SOO) |
|
|
|
{ |
|
|
|
t.self.functor->inplace_copy(self.inplace); |
|
|
|
state = (state_t)(ACTIVE | SOO); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
self.functor = t.self.functor->all_copy(); |
|
|
|
state = (state_t)(ACTIVE | NO_SOO); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
template <typename T> |
|
|
|
function(T& 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); |
|
|
|
if constexpr (!std::is_same_v<T, function>) { |
|
|
|
if constexpr (sizeof(callable<T>) <= sizeof(self)) |
|
|
|
{ |
|
|
|
new((void*)self.inplace) callable<T>(gp::move(t)); |
|
|
|
state = (state_t)(ACTIVE | SOO); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
self.functor = new callable<T>(gp::move(t)); |
|
|
|
state = (state_t)(ACTIVE | NO_SOO); |
|
|
|
} |
|
|
|
} else { |
|
|
|
if(t.state & SOO) |
|
|
|
{ |
|
|
|
auto& ref = t.self.functor; |
|
|
|
ref->inplace_move((char*)&self); |
|
|
|
state = (state_t)(ACTIVE | SOO); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
self.functor = t.self.functor->all_move(); |
|
|
|
state = (state_t)(ACTIVE | NO_SOO); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|