diff --git a/include/gp/function.hpp b/include/gp/function.hpp index 08efa3e..e302e8d 100644 --- a/include/gp/function.hpp +++ b/include/gp/function.hpp @@ -1,6 +1,7 @@ #pragma once #include "gp/exception.hpp" #include "gp/algorithm/tmp_manip.hpp" +#include "gp/algorithm/move.hpp" namespace gp{ template @@ -10,21 +11,24 @@ namespace gp{ class function{ 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 - class callable : public virtual_callable{ - fn internal_representation; + class callable final : public virtual_callable{ + typename gp::remove_reference::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 - function(T t) + 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(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) { + 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); + } + } 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 - function(T& t) + 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); + if constexpr (!std::is_same_v) { + if constexpr (sizeof(callable) <= sizeof(self)) + { + new((void*)self.inplace) callable(gp::move(t)); + state = (state_t)(ACTIVE | SOO); + } + else + { + self.functor = new callable(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); + } } } diff --git a/tests/math.cpp b/tests/math.cpp index 7870865..4d559a6 100644 --- a/tests/math.cpp +++ b/tests/math.cpp @@ -156,12 +156,12 @@ struct function_test : public test_scaffold { virtual int run() { int res = 0; - gp::function l_sdf_b = gp::sphere_sdf({0.0,0.0,0.0}, 1.0); - - gp::function sdf = l_sdf_b; - - gp_config::assertion(sdf(vec3(0,0,0)) == -1, "Bad sdf"); + gp::function l_sdf_b{gp::sphere_sdf({0.0,0.0,0.0}, 1.0)}; + { + gp::function sdf{l_sdf_b}; + gp_config::assertion(l_sdf_b(vec3(0,0,0)) == -1 && sdf(vec3(0,0,0)) == -1, "Bad sdf"); + } return res; } };