diff --git a/smallfun/include/smallfun.hpp b/smallfun/include/smallfun.hpp index 780d896..2328abd 100644 --- a/smallfun/include/smallfun.hpp +++ b/smallfun/include/smallfun.hpp @@ -2,6 +2,8 @@ #define SMALLFUNCTION_SMALLFUNCTION_HPP #include +#include +#include namespace smallfun { @@ -9,7 +11,6 @@ namespace smallfun { template struct SFConcept { virtual ReturnType operator()(Xs...)const = 0; - virtual ReturnType operator()(Xs...) = 0; virtual void copy(void*)const = 0; virtual ~SFConcept() {}; }; @@ -17,59 +18,71 @@ struct SFConcept { template struct SFModel final : SFConcept { - F f; + mutable F f; SFModel(F const& f) : f(f) {} - virtual void copy(void* memory)const { - new (memory) SFModel(f); + void copy(void* memory) const override final { + new (memory) SFModel(f); } - virtual ReturnType operator()(Xs...xs)const { + ReturnType operator()(Xs...xs)const override final { return f(xs...); } - virtual ReturnType operator()(Xs...xs) { - return f(xs...); - } - - virtual ~SFModel() {} }; -template +template struct SmallFun; -template +template class SmallFun { - char memory[size]; + static constexpr std::size_t alignment = alignof(std::max_align_t); + alignas(alignment) char memory[size]; - bool allocated = 0; - using concept = SFConcept; + bool allocated = false; + using Concept = SFConcept; public: SmallFun(){} - template)<=size), bool> = 0 > + template SmallFun(F const&f) - : allocated(sizeof(SFModel)) { - new (memory) SFModel(f); + : allocated(true) { + using Model = SFModel; + static_assert(sizeof(Model) <= size, ""); + new (memory) Model(f); + } + + template + SmallFun& operator=(F const&f) { + using Model = SFModel; + static_assert(sizeof(Model) <= size, ""); + clean(); + allocated = true; + new (memory) Model(f); + return *this; } - template = 0> + + // copy constructor + + template SmallFun(SmallFun const& sf) : allocated(sf.allocated) { + static_assert(s <= size, ""); sf.copy(memory); } - template = 0> + // copy assign + + template SmallFun& operator=(SmallFun const& sf) { + static_assert(s <= size, ""); clean(); allocated = sf.allocated; sf.copy(memory); @@ -78,30 +91,35 @@ class SmallFun { void clean() { if (allocated) { - ((concept*)memory)->~concept(); + Concept *cpt = reinterpret_cast(memory); + cpt->~Concept(); allocated = 0; } } ~SmallFun() { if (allocated) { - ((concept*)memory)->~concept(); + Concept *cpt = reinterpret_cast(memory); + cpt->~Concept(); } } template ReturnType operator()(Ys&&...ys) { - return (*(concept*)memory)(std::forward(ys)...); + Concept *cpt = reinterpret_cast(memory); + return (*cpt)(std::forward(ys)...); } template ReturnType operator()(Ys&&...ys)const { - return (*(concept*)memory)(std::forward(ys)...); + Concept *cpt = reinterpret_cast(memory); + return (*cpt)(std::forward(ys)...); } void copy(void* data)const { if (allocated) { - ((concept*)memory)->copy(data); + Concept *cpt = reinterpret_cast(memory); + cpt->copy(data); } } };