Bluenet  5.7.0
Bluenet, firmware for nRF52 smart home devices
Loading...
Searching...
No Matches
function.h
Go to the documentation of this file.
1/*
2
3License: public domain
4
5From http://probablydance.com/2013/01/13/a-faster-implementation-of-stdfunction/
6
7This is free and unencumbered software released into the public domain.
8
9Anyone is free to copy, modify, publish, use, compile, sell, or
10distribute this software, either in source code form or as a compiled
11binary, for any purpose, commercial or non-commercial, and by any
12means.
13
14In jurisdictions that recognize copyright laws, the author or authors
15of this software dedicate any and all copyright interest in the
16software to the public domain. We make this dedication for the benefit
17of the public at large and to the detriment of our heirs and
18successors. We intend this dedication to be an overt act of
19relinquishment in perpetuity of all present and future rights to this
20software under copyright law.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28OTHER DEALINGS IN THE SOFTWARE.
29
30For more information, please refer to <http://unlicense.org/>
31 */
32// despite that it would be nice if you give credit to Malte Skarupke
33
34#pragma once
35#include <exception>
36#include <functional>
37#include <memory>
38#include <type_traits>
39#include <typeinfo>
40#include <utility>
41
42#ifndef __EXCEPTIONS
43#define FUNC_NO_EXCEPTIONS
44#endif /* __EXCEPTIONS */
45
46#ifdef _MSC_VER
47#define FUNC_NOEXCEPT
48#define FUNC_TEMPLATE_NOEXCEPT(FUNCTOR, ALLOCATOR)
49#define FUNC_CONSTEXPR const
50#else
51#define FUNC_NOEXCEPT noexcept
52#define FUNC_TEMPLATE_NOEXCEPT(FUNCTOR, ALLOCATOR) noexcept(detail::is_inplace_allocated<FUNCTOR, ALLOCATOR>::value)
53#define FUNC_CONSTEXPR constexpr
54#endif
55#ifdef __GNUC__
56#pragma GCC diagnostic push
57#pragma GCC diagnostic ignored "-Wstrict-aliasing"
58#endif
59
60#define FUNC_MOVE(value) static_cast<typename std::remove_reference<decltype(value)>::type&&>(value)
61#define FUNC_FORWARD(type, value) static_cast<type&&>(value)
62
63namespace func {
64#ifndef FUNC_NO_EXCEPTIONS
65struct bad_function_call : std::exception {
66 const char* what() const FUNC_NOEXCEPT override { return "Bad function call"; }
67};
68#endif
69
70template <typename>
71struct force_function_heap_allocation : std::false_type {};
72
73template <typename>
75
76namespace detail {
78struct function_manager;
80protected:
83};
84
85struct empty_struct {};
86
87#ifndef FUNC_NO_EXCEPTIONS
88template <typename Result, typename... Arguments>
89Result empty_call(const functor_padding&, Arguments...) {
90 throw bad_function_call();
91}
92#endif
93
94template <typename T, typename Allocator>
96 static const bool value
97 // so that it fits
98 = sizeof(T) <= sizeof(functor_padding)
99 // so that it will be aligned
100 && std::alignment_of<functor_padding>::value % std::alignment_of<T>::value == 0
101 // so that we can offer noexcept move
102 && std::is_nothrow_move_constructible<T>::value
103 // so that the user can override it
105};
106
107template <typename T>
109 return FUNC_FORWARD(T, func);
110}
111template <typename Result, typename Class, typename... Arguments>
112auto to_functor(Result (Class::*func)(Arguments...)) -> decltype(std::mem_fn(func)) {
113 return std::mem_fn(func);
114}
115template <typename Result, typename Class, typename... Arguments>
116auto to_functor(Result (Class::*func)(Arguments...) const) -> decltype(std::mem_fn(func)) {
117 return std::mem_fn(func);
118}
119
120template <typename T>
122 typedef decltype(to_functor(std::declval<T>())) type;
123};
124
125template <typename T>
126bool is_null(const T&) {
127 return false;
128}
129template <typename Result, typename... Arguments>
130bool is_null(Result (*const& function_pointer)(Arguments...)) {
131 return function_pointer == nullptr;
132}
133template <typename Result, typename Class, typename... Arguments>
134bool is_null(Result (Class::*const& function_pointer)(Arguments...)) {
135 return function_pointer == nullptr;
136}
137template <typename Result, typename Class, typename... Arguments>
138bool is_null(Result (Class::*const& function_pointer)(Arguments...) const) {
139 return function_pointer == nullptr;
140}
141
142template <typename, typename>
144 static const bool value = false;
145};
146
147template <typename Result, typename... Arguments>
148struct is_valid_function_argument<function<Result(Arguments...)>, Result(Arguments...)> {
149 static const bool value = false;
150};
151
152template <typename T, typename Result, typename... Arguments>
153struct is_valid_function_argument<T, Result(Arguments...)> {
154#ifdef _MSC_VER
155 // as of january 2013 visual studio doesn't support the SFINAE below
156 static const bool value = true;
157#else
158 template <typename U>
159 static decltype(to_functor(std::declval<U>())(std::declval<Arguments>()...)) check(U*);
160 template <typename>
161 static empty_struct check(...);
162
163 static const bool value = std::is_convertible<decltype(check<T>(nullptr)), Result>::value;
164#endif
165};
166
168
170 template <typename Allocator>
172 return reinterpret_cast<Allocator&>(manager);
173 }
174 template <typename Allocator>
175 const Allocator& get_allocator() const FUNC_NOEXCEPT {
176 return reinterpret_cast<const Allocator&>(manager);
177 }
178
181};
182
183template <typename T, typename Allocator, typename Enable = void>
185 template <typename Result, typename... Arguments>
186 static Result call(const functor_padding& storage, Arguments... arguments) {
187 // do not call get_functor_ref because I want this function to be fast
188 // in debug when nothing gets inlined
189 return const_cast<T&>(reinterpret_cast<const T&>(storage))(FUNC_FORWARD(Arguments, arguments)...);
190 }
191
192 static void store_functor(manager_storage_type& storage, T to_store) {
193 new (&get_functor_ref(storage)) T(FUNC_FORWARD(T, to_store));
194 }
196 new (&get_functor_ref(lhs)) T(FUNC_MOVE(get_functor_ref(rhs)));
197 }
198 static void destroy_functor(Allocator&, manager_storage_type& storage) FUNC_NOEXCEPT {
199 get_functor_ref(storage).~T();
200 }
202 return const_cast<T&>(reinterpret_cast<const T&>(storage.functor));
203 }
204};
205template <typename T, typename Allocator>
207 T,
208 Allocator,
209 typename std::enable_if<!is_inplace_allocated<T, Allocator>::value>::type> {
210 template <typename Result, typename... Arguments>
211 static Result call(const functor_padding& storage, Arguments... arguments) {
212 // do not call get_functor_ptr_ref because I want this function to be fast
213 // in debug when nothing gets inlined
214 return (*reinterpret_cast<const typename std::allocator_traits<Allocator>::pointer&>(storage))(
215 FUNC_FORWARD(Arguments, arguments)...);
216 }
217
218 static void store_functor(manager_storage_type& self, T to_store) {
219 Allocator& allocator = self.get_allocator<Allocator>();
220 ;
221 static_assert(
222 sizeof(typename std::allocator_traits<Allocator>::pointer) <= sizeof(self.functor),
223 "The allocator's pointer type is too big");
224 typename std::allocator_traits<Allocator>::pointer* ptr =
225 new (&get_functor_ptr_ref(self)) typename std::allocator_traits<Allocator>::pointer(
226 std::allocator_traits<Allocator>::allocate(allocator, 1));
227 std::allocator_traits<Allocator>::construct(allocator, *ptr, FUNC_FORWARD(T, to_store));
228 }
230 static_assert(
231 std::is_nothrow_move_constructible<typename std::allocator_traits<Allocator>::pointer>::value,
232 "we can't offer a noexcept swap if the pointer type is not nothrow move constructible");
233 new (&get_functor_ptr_ref(lhs))
234 typename std::allocator_traits<Allocator>::pointer(FUNC_MOVE(get_functor_ptr_ref(rhs)));
235 // this next assignment makes the destroy function easier
236 get_functor_ptr_ref(rhs) = nullptr;
237 }
238 static void destroy_functor(Allocator& allocator, manager_storage_type& storage) FUNC_NOEXCEPT {
239 typename std::allocator_traits<Allocator>::pointer& pointer = get_functor_ptr_ref(storage);
240 if (!pointer) return;
241 std::allocator_traits<Allocator>::destroy(allocator, pointer);
242 std::allocator_traits<Allocator>::deallocate(allocator, pointer, 1);
243 }
245 return *get_functor_ptr_ref(storage);
246 }
247 static typename std::allocator_traits<Allocator>::pointer& get_functor_ptr_ref(manager_storage_type& storage)
249 return reinterpret_cast<typename std::allocator_traits<Allocator>::pointer&>(storage.functor);
250 }
251 static const typename std::allocator_traits<Allocator>::pointer& get_functor_ptr_ref(
252 const manager_storage_type& storage) FUNC_NOEXCEPT {
253 return reinterpret_cast<const typename std::allocator_traits<Allocator>::pointer&>(storage.functor);
254 }
255};
256
257template <typename T, typename Allocator>
258static const function_manager& get_default_manager();
259
260template <typename T, typename Allocator>
261static void create_manager(manager_storage_type& storage, Allocator&& allocator) {
262 new (&storage.get_allocator<Allocator>()) Allocator(FUNC_MOVE(allocator));
263 storage.manager = &get_default_manager<T, Allocator>();
264}
265
266// this struct acts as a vtable. it is an optimization to prevent
267// code-bloat from rtti. see the documentation of boost::function
269 template <typename T, typename Allocator>
271#ifdef _MSC_VER
272 function_manager result =
273#else
274 return function_manager
275#endif
276 {&templated_call_move_and_destroy<T, Allocator>,
277 &templated_call_copy<T, Allocator>,
278 &templated_call_copy_functor_only<T, Allocator>,
279 &templated_call_destroy<T, Allocator>,
280#ifndef FUNC_NO_RTTI
281 &templated_call_type_id<T, Allocator>,
282 &templated_call_target<T, Allocator>
283#endif
284 };
285#ifdef _MSC_VER
286 return result;
287#endif
288 }
289
291 void (*const call_copy)(manager_storage_type& lhs, const manager_storage_type& rhs);
293 void (*const call_destroy)(manager_storage_type& manager);
294#ifndef FUNC_NO_RTTI
295 const std::type_info& (*const call_type_id)();
296 void* (*const call_target)(const manager_storage_type& manager, const std::type_info& type);
297#endif
298
299 template <typename T, typename Allocator>
302 specialization::move_functor(lhs, FUNC_MOVE(rhs));
303 specialization::destroy_functor(rhs.get_allocator<Allocator>(), rhs);
304 create_manager<T, Allocator>(lhs, FUNC_MOVE(rhs.get_allocator<Allocator>()));
305 rhs.get_allocator<Allocator>().~Allocator();
306 }
307 template <typename T, typename Allocator>
310 create_manager<T, Allocator>(lhs, Allocator(rhs.get_allocator<Allocator>()));
311 specialization::store_functor(lhs, specialization::get_functor_ref(rhs));
312 }
313 template <typename T, typename Allocator>
316 specialization::destroy_functor(self.get_allocator<Allocator>(), self);
317 self.get_allocator<Allocator>().~Allocator();
318 }
319 template <typename T, typename Allocator>
322 specialization::store_functor(lhs, specialization::get_functor_ref(rhs));
323 }
324#ifndef FUNC_NO_RTTI
325 template <typename T, typename>
326 static const std::type_info& templated_call_type_id() {
327 return typeid(T);
328 }
329 template <typename T, typename Allocator>
330 static void* templated_call_target(const manager_storage_type& self, const std::type_info& type) {
332 if (type == typeid(T))
333 return &specialization::get_functor_ref(self);
334 else
335 return nullptr;
336 }
337#endif
338};
339template <typename T, typename Allocator>
340inline static const function_manager& get_default_manager() {
341 static FUNC_CONSTEXPR function_manager default_manager = function_manager::create_default_manager<T, Allocator>();
342 return default_manager;
343}
344
345template <typename Result, typename...>
347 typedef Result result_type;
348};
349template <typename Result, typename Argument>
351 typedef Result result_type;
352 typedef Argument argument_type;
353};
354template <typename Result, typename First_Argument, typename Second_Argument>
356 typedef Result result_type;
357 typedef First_Argument first_argument_type;
358 typedef Second_Argument second_argument_type;
359};
360} // namespace detail
361
362template <typename Result, typename... Arguments>
363class function<Result(Arguments...)> : public detail::typedeffer<Result, Arguments...> {
364public:
365 function() FUNC_NOEXCEPT { initialize_empty(); }
366 function(std::nullptr_t) FUNC_NOEXCEPT { initialize_empty(); }
368 initialize_empty();
369 swap(other);
370 }
371 function(const function& other) : call(other.call) {
372 other.manager_storage.manager->call_copy(manager_storage, other.manager_storage);
373 }
374 template <typename T>
376 T functor,
377 typename std::enable_if<
378 detail::is_valid_function_argument<T, Result(Arguments...)>::value,
380 FUNC_TEMPLATE_NOEXCEPT(T, std::allocator<typename detail::functor_type<T>::type>) {
381 if (detail::is_null(functor)) {
382 initialize_empty();
383 }
384 else {
385 typedef typename detail::functor_type<T>::type functor_type;
386 initialize(detail::to_functor(FUNC_FORWARD(T, functor)), std::allocator<functor_type>());
387 }
388 }
389 template <typename Allocator>
390 function(std::allocator_arg_t, const Allocator&) {
391 // ignore the allocator because I don't allocate
392 initialize_empty();
393 }
394 template <typename Allocator>
395 function(std::allocator_arg_t, const Allocator&, std::nullptr_t) {
396 // ignore the allocator because I don't allocate
397 initialize_empty();
398 }
399 template <typename Allocator, typename T>
400 function(
401 std::allocator_arg_t,
402 const Allocator& allocator,
403 T functor,
404 typename std::enable_if<
405 detail::is_valid_function_argument<T, Result(Arguments...)>::value,
406 detail::empty_struct>::type = detail::empty_struct()) FUNC_TEMPLATE_NOEXCEPT(T, Allocator) {
407 if (detail::is_null(functor)) {
408 initialize_empty();
409 }
410 else {
411 initialize(detail::to_functor(FUNC_FORWARD(T, functor)), Allocator(allocator));
412 }
413 }
414 template <typename Allocator>
415 function(std::allocator_arg_t, const Allocator& allocator, const function& other) : call(other.call) {
416 typedef typename std::allocator_traits<Allocator>::template rebind_alloc<function> MyAllocator;
417
418 // first try to see if the allocator matches the target type
419 detail::manager_type manager_for_allocator =
420 &detail::get_default_manager<typename std::allocator_traits<Allocator>::value_type, Allocator>();
421 if (other.manager_storage.manager == manager_for_allocator) {
422 detail::create_manager<typename std::allocator_traits<Allocator>::value_type, Allocator>(
423 manager_storage, Allocator(allocator));
424 manager_for_allocator->call_copy_functor_only(manager_storage, other.manager_storage);
425 }
426 // if it does not, try to see if the target contains my type. this
427 // breaks the recursion of the last case. otherwise repeated copies
428 // would allocate more and more memory
429 else {
430 detail::manager_type manager_for_function = &detail::get_default_manager<function, MyAllocator>();
431 if (other.manager_storage.manager == manager_for_function) {
432 detail::create_manager<function, MyAllocator>(manager_storage, MyAllocator(allocator));
433 manager_for_function->call_copy_functor_only(manager_storage, other.manager_storage);
434 }
435 else {
436 // else store the other function as my target
437 initialize(other, MyAllocator(allocator));
438 }
439 }
440 }
441 template <typename Allocator>
442 function(std::allocator_arg_t, const Allocator&, function&& other) FUNC_NOEXCEPT {
443 // ignore the allocator because I don't allocate
444 initialize_empty();
445 swap(other);
446 }
447
448 function& operator=(function other) FUNC_NOEXCEPT {
449 swap(other);
450 return *this;
451 }
452 ~function() FUNC_NOEXCEPT { manager_storage.manager->call_destroy(manager_storage); }
453
454 Result operator()(Arguments... arguments) const {
455 return call(manager_storage.functor, FUNC_FORWARD(Arguments, arguments)...);
456 }
457
458 template <typename T, typename Allocator>
459 void assign(T&& functor, const Allocator& allocator) FUNC_TEMPLATE_NOEXCEPT(T, Allocator) {
460 function(std::allocator_arg, allocator, functor).swap(*this);
461 }
462
463 void swap(function& other) FUNC_NOEXCEPT {
464 detail::manager_storage_type temp_storage;
465 other.manager_storage.manager->call_move_and_destroy(temp_storage, FUNC_MOVE(other.manager_storage));
466 manager_storage.manager->call_move_and_destroy(other.manager_storage, FUNC_MOVE(manager_storage));
467 temp_storage.manager->call_move_and_destroy(manager_storage, FUNC_MOVE(temp_storage));
468
469 std::swap(call, other.call);
470 }
471
472#ifndef FUNC_NO_RTTI
473 const std::type_info& target_type() const FUNC_NOEXCEPT {
474 return manager_storage.manager->call_type_id();
475 }
476 template <typename T>
477 T* target() FUNC_NOEXCEPT {
478 return static_cast<T*>(manager_storage.manager->call_target(manager_storage, typeid(T)));
479 }
480 template <typename T>
481 const T* target() const FUNC_NOEXCEPT {
482 return static_cast<const T*>(manager_storage.manager->call_target(manager_storage, typeid(T)));
483 }
484#endif
485
486 operator bool() const FUNC_NOEXCEPT {
487
488#ifdef FUNC_NO_EXCEPTIONS
489 return call != nullptr;
490#else
491 return call != &detail::empty_call<Result, Arguments...>;
492#endif
493 }
494
495private:
496 detail::manager_storage_type manager_storage;
497 Result (*call)(const detail::functor_padding&, Arguments...);
498
499 template <typename T, typename Allocator>
500 void initialize(T functor, Allocator&& allocator) {
502 detail::create_manager<T, Allocator>(manager_storage, FUNC_FORWARD(Allocator, allocator));
504 manager_storage, FUNC_FORWARD(T, functor));
505 }
506
507 typedef Result (*Empty_Function_Type)(Arguments...);
509 typedef std::allocator<Empty_Function_Type> Allocator;
510 static_assert(
512 "The empty function should benefit from small functor optimization");
513
514 detail::create_manager<Empty_Function_Type, Allocator>(manager_storage, Allocator());
516 manager_storage, nullptr);
517#ifdef FUNC_NO_EXCEPTIONS
518 call = nullptr;
519#else
520 call = &detail::empty_call<Result, Arguments...>;
521#endif
522 }
523};
524
525template <typename T>
526bool operator==(std::nullptr_t, const function<T>& rhs) FUNC_NOEXCEPT {
527 return !rhs;
528}
529template <typename T>
530bool operator==(const function<T>& lhs, std::nullptr_t) FUNC_NOEXCEPT {
531 return !lhs;
532}
533template <typename T>
534bool operator!=(std::nullptr_t, const function<T>& rhs) FUNC_NOEXCEPT {
535 return rhs;
536}
537template <typename T>
538bool operator!=(const function<T>& lhs, std::nullptr_t) FUNC_NOEXCEPT {
539 return lhs;
540}
541
542template <typename T>
543void swap(function<T>& lhs, function<T>& rhs) {
544 lhs.swap(rhs);
545}
546
547} // end namespace func
548
549namespace std {
550template <typename Result, typename... Arguments, typename Allocator>
551struct uses_allocator<func::function<Result(Arguments...)>, Allocator> : std::true_type {};
552} // namespace std
553
554#ifdef USING_FUNC
555
556using func::function;
557#else /* USING_FUNC */
558
559using std::function;
560
561#endif
562
563#ifdef __GNUC__
564#pragma GCC diagnostic pop
565#endif
566#undef FUNC_NOEXCEPT
567#undef FUNC_TEMPLATE_NOEXCEPT
568#undef FUNC_FORWARD
569#undef FUNC_MOVE
570#undef FUNC_CONSTEXPR
function(const function &other)
Definition: function.h:371
void initialize(T functor, Allocator &&allocator)
Definition: function.h:500
function() FUNC_NOEXCEPT
Definition: function.h:365
function(T functor, typename std::enable_if< detail::is_valid_function_argument< T, Result(Arguments...)>::value, detail::empty_struct >::type=detail::empty_struct()) FUNC_TEMPLATE_NOEXCEPT(T
function(std::nullptr_t) FUNC_NOEXCEPT
Definition: function.h:366
function(function &&other) FUNC_NOEXCEPT
Definition: function.h:367
void initialize_empty() FUNC_NOEXCEPT
Definition: function.h:508
Definition: function.h:74
#define FUNC_CONSTEXPR
Definition: function.h:53
#define FUNC_FORWARD(type, value)
Definition: function.h:61
#define FUNC_TEMPLATE_NOEXCEPT(FUNCTOR, ALLOCATOR)
Definition: function.h:52
#define FUNC_MOVE(value)
Definition: function.h:60
#define FUNC_NOEXCEPT
Definition: function.h:51
bool is_null(const T &)
Definition: function.h:126
T to_functor(T &&func)
Definition: function.h:108
const function_manager * manager_type
Definition: function.h:167
static const function_manager & get_default_manager()
Definition: function.h:340
static void create_manager(manager_storage_type &storage, Allocator &&allocator)
Definition: function.h:261
Definition: function.h:63
void swap(function< T > &lhs, function< T > &rhs)
Definition: function.h:543
bool operator!=(std::nullptr_t, const function< T > &rhs) FUNC_NOEXCEPT
Definition: function.h:534
bool operator==(std::nullptr_t, const function< T > &rhs) FUNC_NOEXCEPT
Definition: function.h:526
Definition: function.h:549
Definition: function.h:85
static void destroy_functor(Allocator &allocator, manager_storage_type &storage) FUNC_NOEXCEPT
Definition: function.h:238
static const std::allocator_traits< Allocator >::pointer & get_functor_ptr_ref(const manager_storage_type &storage) FUNC_NOEXCEPT
Definition: function.h:251
static void move_functor(manager_storage_type &lhs, manager_storage_type &&rhs) FUNC_NOEXCEPT
Definition: function.h:229
static std::allocator_traits< Allocator >::pointer & get_functor_ptr_ref(manager_storage_type &storage) FUNC_NOEXCEPT
Definition: function.h:247
static void move_functor(manager_storage_type &lhs, manager_storage_type &&rhs) FUNC_NOEXCEPT
Definition: function.h:195
static void store_functor(manager_storage_type &storage, T to_store)
Definition: function.h:192
static Result call(const functor_padding &storage, Arguments... arguments)
Definition: function.h:186
static T & get_functor_ref(const manager_storage_type &storage) FUNC_NOEXCEPT
Definition: function.h:201
static void destroy_functor(Allocator &, manager_storage_type &storage) FUNC_NOEXCEPT
Definition: function.h:198
Definition: function.h:268
static void templated_call_copy(manager_storage_type &lhs, const manager_storage_type &rhs)
Definition: function.h:308
static FUNC_CONSTEXPR function_manager create_default_manager()
Definition: function.h:270
void(*const call_copy)(manager_storage_type &lhs, const manager_storage_type &rhs)
Definition: function.h:291
static void templated_call_destroy(manager_storage_type &self)
Definition: function.h:314
static void templated_call_copy_functor_only(manager_storage_type &lhs, const manager_storage_type &rhs)
Definition: function.h:320
static void * templated_call_target(const manager_storage_type &self, const std::type_info &type)
Definition: function.h:330
void(*const call_move_and_destroy)(manager_storage_type &lhs, manager_storage_type &&rhs)
Definition: function.h:290
const std::type_info &(*const call_type_id)()
Definition: function.h:295
static const std::type_info & templated_call_type_id()
Definition: function.h:326
void(*const call_copy_functor_only)(manager_storage_type &lhs, const manager_storage_type &rhs)
Definition: function.h:292
void(*const call_destroy)(manager_storage_type &manager)
Definition: function.h:293
void *(*const call_target)(const manager_storage_type &manager, const std::type_info &type)
Definition: function.h:296
static void templated_call_move_and_destroy(manager_storage_type &lhs, manager_storage_type &&rhs)
Definition: function.h:300
Definition: function.h:79
size_t padding_second
Definition: function.h:82
size_t padding_first
Definition: function.h:81
Definition: function.h:121
decltype(to_functor(std::declval< T >())) type
Definition: function.h:122
Definition: function.h:95
static const bool value
Definition: function.h:98
static decltype(to_functor(std::declval< U >())(std::declval< Arguments >()...)) check(U *)
static const bool value
Definition: function.h:144
Definition: function.h:169
const Allocator & get_allocator() const FUNC_NOEXCEPT
Definition: function.h:175
Allocator & get_allocator() FUNC_NOEXCEPT
Definition: function.h:171
manager_type manager
Definition: function.h:180
functor_padding functor
Definition: function.h:179
Argument argument_type
Definition: function.h:352
Result result_type
Definition: function.h:351
Second_Argument second_argument_type
Definition: function.h:358
First_Argument first_argument_type
Definition: function.h:357
Definition: function.h:346
Result result_type
Definition: function.h:347
Definition: function.h:71