From ce350703c4bf4f7f8ef1b9572c943c5adc73d0b8 Mon Sep 17 00:00:00 2001 From: user706 <39215612+user706@users.noreply.github.com> Date: Sat, 14 Jul 2018 23:49:02 +0200 Subject: [PATCH] - fix gcc warning warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] with 2 lines splitup: Concept *cpt = reinterpret_cast(memory); cpt->~Concept(); - use std::size_t instead of unsigned - align according to alignof(std::max_align_t) - use mutable F to get the following functor compiled: struct Func1 { int operator()(int val) // const { return val * 2; } int a[10]; }; - use static_assert instead of enable_if - add: SmallFun& operator=(F const&f) --- smallfun/include/smallfun.hpp | 74 ++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 28 deletions(-) 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); } } };