join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
function.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_CORE_FUNCTION_HPP
26#define JOIN_CORE_FUNCTION_HPP
27
28// C++.
29#include <type_traits>
30#include <functional>
31#include <utility>
32#include <new>
33
34// C.
35#include <cstddef>
36
37namespace join
38{
42 template <typename Signature, std::size_t Capacity = 32, std::size_t Alignment = alignof (std::max_align_t)>
43 class Function;
44
48 template <typename Return, typename... Args, std::size_t Capacity, std::size_t Alignment>
49 class Function<Return (Args...), Capacity, Alignment>
50 {
51 public:
55 Function () noexcept = default;
56
61 Function (const Function& other) = delete;
62
68 Function& operator= (const Function& other) = delete;
69
74 Function (Function&& other) noexcept
75 {
76 moveFrom (std::move (other));
77 }
78
84 Function& operator= (Function&& other) noexcept
85 {
86 clear ();
87 moveFrom (std::move (other));
88 return *this;
89 }
90
94 Function (std::nullptr_t) noexcept
95 : Function ()
96 {
97 }
98
102 Function& operator= (std::nullptr_t) noexcept
103 {
104 clear ();
105 return *this;
106 }
107
112 template <typename Func, typename DecayedFunc = std::decay_t<Func>,
113 typename = std::enable_if_t<
114 !std::is_same<DecayedFunc, Function>::value &&
115 (std::is_void<Return>::value ||
116 std::is_convertible<typename std::result_of<DecayedFunc&(Args...)>::type, Return>::value)>>
117 Function (Func&& callable)
118 {
119 static_assert (sizeof (DecayedFunc) <= Capacity, "Callable size exceeds Function capacity.");
120 static_assert (alignof (DecayedFunc) <= Alignment, "Callable alignment exceeds Function alignment.");
121 static_assert (std::is_nothrow_move_constructible<DecayedFunc>::value,
122 "Callable must be nothrow move constructible.");
123
124 new (&_storage) DecayedFunc (std::forward<Func> (callable));
125
126 _invoker = [] (void* storage, Args&&... args) -> Return {
127 return static_cast<Return> ((*static_cast<DecayedFunc*> (storage)) (std::forward<Args> (args)...));
128 };
129
130 _manager = [] (void* dst, void* src) noexcept {
131 DecayedFunc* source = static_cast<DecayedFunc*> (src);
132 new (dst) DecayedFunc (std::move (*source));
133 source->~DecayedFunc ();
134 };
135
136 _destructor = [] (void* storage) noexcept {
137 static_cast<DecayedFunc*> (storage)->~DecayedFunc ();
138 };
139 }
140
145 {
146 clear ();
147 }
148
155 Return operator() (Args&&... args)
156 {
157 if (!_invoker)
158 {
159 throw std::bad_function_call ();
160 }
161 return _invoker (&_storage, std::forward<Args> (args)...);
162 }
163
168 explicit operator bool () const noexcept
169 {
170 return _invoker != nullptr;
171 }
172
176 void reset () noexcept
177 {
178 clear ();
179 }
180
184 void swap (Function& other) noexcept
185 {
186 Function tmp (std::move (other));
187 other = std::move (*this);
188 *this = std::move (tmp);
189 }
190
191 private:
193 using InvokerFunc = Return (*) (void*, Args&&...);
194
196 using ManagerFunc = void (*) (void*, void*);
197
199 using DestructorFunc = void (*) (void*);
200
204 void clear () noexcept
205 {
206 if (_destructor)
207 {
208 _destructor (&_storage);
209 _invoker = nullptr;
210 _manager = nullptr;
211 _destructor = nullptr;
212 }
213 }
214
218 void moveFrom (Function&& other) noexcept
219 {
220 _invoker = other._invoker;
221 _manager = other._manager;
222 _destructor = other._destructor;
223
224 if (_manager)
225 {
226 _manager (&_storage, &other._storage);
227 other._invoker = nullptr;
228 other._manager = nullptr;
229 other._destructor = nullptr;
230 }
231 }
232
234 alignas (Alignment) unsigned char _storage[Capacity];
235
237 InvokerFunc _invoker = nullptr;
238
240 ManagerFunc _manager = nullptr;
241
243 DestructorFunc _destructor = nullptr;
244 };
245}
246
247#endif
Function(Func &&callable)
construct with a callable object.
Definition function.hpp:117
void reset() noexcept
clear the stored callable.
Definition function.hpp:176
Function(std::nullptr_t) noexcept
construct from nullptr.
Definition function.hpp:94
void swap(Function &other) noexcept
swap two Function instances.
Definition function.hpp:184
~Function()
destructor.
Definition function.hpp:144
Function() noexcept=default
default constructor.
fixed-capacity move-only allocation-free alternative to std::function.
Definition function.hpp:43
Definition acceptor.hpp:32