14 #define FUNC_TEMPLATE_NOEXCEPT(FUNCTOR, ALLOCATOR) 15 #define FUNC_CONSTEXPR const 17 #define FUNC_NOEXCEPT noexcept 18 #define FUNC_TEMPLATE_NOEXCEPT(FUNCTOR, ALLOCATOR) noexcept(detail::is_inplace_allocated<FUNCTOR, ALLOCATOR>::value) 19 #define FUNC_CONSTEXPR constexpr 22 #pragma GCC diagnostic push 23 #pragma GCC diagnostic ignored "-Wstrict-aliasing" 26 #define FUNC_MOVE(value) static_cast<typename std::remove_reference<decltype(value)>::type &&>(value) 27 #define FUNC_FORWARD(type, value) static_cast<type &&>(value) 31 #ifndef FUNC_NO_EXCEPTIONS 36 return "Bad function call";
65 # ifndef FUNC_NO_EXCEPTIONS 66 template<
typename Result,
typename... Arguments>
73 template<
typename T,
typename Allocator>
76 static const bool value
80 && std::alignment_of<functor_padding>::value % std::alignment_of<T>::value == 0
82 && std::is_nothrow_move_constructible<T>::value
92 template<
typename Result,
typename Class,
typename... Arguments>
93 auto to_functor(Result (Class::*
func)(Arguments...)) -> decltype(std::mem_fn(func))
95 return std::mem_fn(func);
97 template<
typename Result,
typename Class,
typename... Arguments>
98 auto to_functor(Result (Class::*func)(Arguments...)
const) -> decltype(std::mem_fn(func))
100 return std::mem_fn(func);
114 template<
typename Result,
typename... Arguments>
115 bool is_null(Result (*
const & function_pointer)(Arguments...))
117 return function_pointer ==
nullptr;
119 template<
typename Result,
typename Class,
typename... Arguments>
120 bool is_null(Result (Class::*
const & function_pointer)(Arguments...))
122 return function_pointer ==
nullptr;
124 template<
typename Result,
typename Class,
typename... Arguments>
125 bool is_null(Result (Class::*
const & function_pointer)(Arguments...)
const)
127 return function_pointer ==
nullptr;
130 template<
typename,
typename>
133 static const bool value =
false;
136 template<
typename Result,
typename... Arguments>
139 static const bool value =
false;
142 template<
typename T,
typename Result,
typename... Arguments>
147 static const bool value =
true;
150 static decltype(
to_functor(std::declval<U>())(std::declval<Arguments>()...)) check(U *);
154 static const bool value = std::is_convertible<decltype(check<T>(
nullptr)), Result>::value;
162 template<
typename Allocator>
165 return reinterpret_cast<Allocator &
>(manager);
167 template<
typename Allocator>
170 return reinterpret_cast<const Allocator &
>(manager);
177 template<
typename T,
typename Allocator,
typename Enable =
void>
180 template<
typename Result,
typename... Arguments>
185 return const_cast<T &
>(
reinterpret_cast<const T &
>(storage))(
FUNC_FORWARD(Arguments, arguments)...);
190 new (&get_functor_ref(storage)) T(
FUNC_FORWARD(T, to_store));
194 new (&get_functor_ref(lhs)) T(
FUNC_MOVE(get_functor_ref(rhs)));
198 get_functor_ref(storage).~T();
202 return const_cast<T &
>(
reinterpret_cast<const T &
>(storage.functor));
205 template<
typename T,
typename Allocator>
208 template<
typename Result,
typename... Arguments>
213 return (*
reinterpret_cast<const typename std::allocator_traits<Allocator>::pointer &
>(storage))(
FUNC_FORWARD(Arguments, arguments)...);
219 static_assert(
sizeof(
typename std::allocator_traits<Allocator>::pointer) <=
sizeof(
self.functor),
"The allocator's pointer type is too big");
220 typename std::allocator_traits<Allocator>::pointer * ptr =
new (&get_functor_ptr_ref(
self))
typename std::allocator_traits<Allocator>::pointer(std::allocator_traits<Allocator>::allocate(allocator, 1));
221 std::allocator_traits<Allocator>::construct(allocator, *ptr,
FUNC_FORWARD(T, to_store));
225 static_assert(std::is_nothrow_move_constructible<
typename std::allocator_traits<Allocator>::pointer>::value,
"we can't offer a noexcept swap if the pointer type is not nothrow move constructible");
226 new (&get_functor_ptr_ref(lhs))
typename std::allocator_traits<Allocator>::pointer(
FUNC_MOVE(get_functor_ptr_ref(rhs)));
228 get_functor_ptr_ref(rhs) =
nullptr;
232 typename std::allocator_traits<Allocator>::pointer & pointer = get_functor_ptr_ref(storage);
233 if (!pointer)
return;
234 std::allocator_traits<Allocator>::destroy(allocator, pointer);
235 std::allocator_traits<Allocator>::deallocate(allocator, pointer, 1);
239 return *get_functor_ptr_ref(storage);
243 return reinterpret_cast<typename std::allocator_traits<Allocator>::pointer &
>(storage.functor);
247 return reinterpret_cast<const typename std::allocator_traits<Allocator>::pointer &
>(storage.functor);
251 template<
typename T,
typename Allocator>
254 template<
typename T,
typename Allocator>
258 storage.
manager = &get_default_manager<T, Allocator>();
265 template<
typename T,
typename Allocator>
274 &templated_call_move_and_destroy<T, Allocator>,
275 &templated_call_copy<T, Allocator>,
276 &templated_call_copy_functor_only<T, Allocator>,
277 &templated_call_destroy<T, Allocator>,
278 # ifndef FUNC_NO_RTTI 279 &templated_call_type_id<T, Allocator>,
280 &templated_call_target<T, Allocator>
292 # ifndef FUNC_NO_RTTI 297 template<
typename T,
typename Allocator>
301 specialization::move_functor(lhs,
FUNC_MOVE(rhs));
302 specialization::destroy_functor(rhs.get_allocator<
Allocator>(), rhs);
306 template<
typename T,
typename Allocator>
311 specialization::store_functor(lhs, specialization::get_functor_ref(rhs));
313 template<
typename T,
typename Allocator>
317 specialization::destroy_functor(
self.get_allocator<Allocator>(),
self);
320 template<
typename T,
typename Allocator>
324 specialization::store_functor(lhs, specialization::get_functor_ref(rhs));
326 # ifndef FUNC_NO_RTTI 327 template<
typename T,
typename>
332 template<
typename T,
typename Allocator>
336 if (type ==
typeid(T))
337 return &specialization::get_functor_ref(
self);
343 template<
typename T,
typename Allocator>
347 return default_manager;
350 template<
typename Result,
typename...>
355 template<
typename Result,
typename Argument>
361 template<
typename Result,
typename First_Argument,
typename Second_Argument>
370 template<
typename Result,
typename... Arguments>
388 function(
const function & other)
391 other.manager_storage.manager->call_copy(manager_storage, other.manager_storage);
407 template<
typename Allocator>
408 function(std::allocator_arg_t,
const Allocator &)
413 template<
typename Allocator>
414 function(std::allocator_arg_t,
const Allocator &, std::nullptr_t)
419 template<
typename Allocator,
typename T>
420 function(std::allocator_arg_t,
const Allocator & allocator, T functor,
433 template<
typename Allocator>
434 function(std::allocator_arg_t,
const Allocator & allocator,
const function & other)
437 typedef typename std::allocator_traits<Allocator>::template rebind_alloc<function> MyAllocator;
440 detail::manager_type manager_for_allocator = &detail::get_default_manager<typename std::allocator_traits<Allocator>::value_type, Allocator>();
441 if (other.manager_storage.manager == manager_for_allocator)
443 detail::create_manager<typename std::allocator_traits<Allocator>::value_type, Allocator>(manager_storage, Allocator(allocator));
451 detail::manager_type manager_for_function = &detail::get_default_manager<function, MyAllocator>();
452 if (other.manager_storage.manager == manager_for_function)
454 detail::create_manager<function, MyAllocator>(manager_storage, MyAllocator(allocator));
460 initialize(other, MyAllocator(allocator));
464 template<
typename Allocator>
465 function(std::allocator_arg_t,
const Allocator &,
function && other)
FUNC_NOEXCEPT 479 manager_storage.manager->call_destroy(manager_storage);
482 Result operator()(Arguments... arguments)
const 484 return call(manager_storage.functor,
FUNC_FORWARD(Arguments, arguments)...);
487 template<
typename T,
typename Allocator>
490 function(std::allocator_arg, allocator, functor).
swap(*
this);
497 manager_storage.manager->call_move_and_destroy(other.manager_storage,
FUNC_MOVE(manager_storage));
504 # ifndef FUNC_NO_RTTI 507 return manager_storage.manager->call_type_id();
512 return static_cast<T *
>(manager_storage.manager->call_target(manager_storage,
typeid(T)));
517 return static_cast<const T *
>(manager_storage.manager->call_target(manager_storage,
typeid(T)));
524 # ifdef FUNC_NO_EXCEPTIONS 525 return call !=
nullptr;
535 template<
typename T,
typename Allocator>
539 detail::create_manager<T, Allocator>(manager_storage,
FUNC_FORWARD(Allocator, allocator));
543 typedef Result(*Empty_Function_Type)(Arguments...);
546 typedef std::allocator<Empty_Function_Type> Allocator;
549 detail::create_manager<Empty_Function_Type, Allocator>(manager_storage, Allocator());
551 # ifdef FUNC_NO_EXCEPTIONS 590 template<
typename Result,
typename... Arguments,
typename Allocator>
591 struct uses_allocator<func::function<Result (Arguments...)>,
Allocator>
598 #pragma GCC diagnostic pop 601 #undef FUNC_TEMPLATE_NOEXCEPT 604 #undef FUNC_CONSTEXPR static void destroy_functor(Allocator &, manager_storage_type &storage) FUNC_NOEXCEPT
static void create_manager(manager_storage_type &storage, Allocator &&allocator)
static void templated_call_copy_functor_only(manager_storage_type &lhs, const manager_storage_type &rhs)
static const function_manager & get_default_manager()
static const std::allocator_traits< Allocator >::pointer & get_functor_ptr_ref(const manager_storage_type &storage) FUNC_NOEXCEPT
const function_manager * manager_type
static Result call(const functor_padding &storage, Arguments...arguments)
bool operator!=(std::nullptr_t, const function< T > &rhs) FUNC_NOEXCEPT
Allocator & get_allocator() FUNC_NOEXCEPT
static const std::type_info & templated_call_type_id()
#define FUNC_TEMPLATE_NOEXCEPT(FUNCTOR, ALLOCATOR)
static void * templated_call_target(const manager_storage_type &self, const std::type_info &type)
static void store_functor(manager_storage_type &self, T to_store)
bool_constant< true > true_type
static void store_functor(manager_storage_type &storage, T to_store)
static void destroy_functor(Allocator &allocator, manager_storage_type &storage) FUNC_NOEXCEPT
bool_constant< false > false_type
static void move_functor(manager_storage_type &lhs, manager_storage_type &&rhs) FUNC_NOEXCEPT
Second_Argument second_argument_type
void *(*const call_target)(const manager_storage_type &manager, const std::type_info &type)
static FUNC_CONSTEXPR function_manager create_default_manager()
void(*const call_move_and_destroy)(manager_storage_type &lhs, manager_storage_type &&rhs)
const Allocator & get_allocator() const FUNC_NOEXCEPT
static void templated_call_move_and_destroy(manager_storage_type &lhs, manager_storage_type &&rhs)
static void templated_call_copy(manager_storage_type &lhs, const manager_storage_type &rhs)
static T & get_functor_ref(const manager_storage_type &storage) FUNC_NOEXCEPT
static T & get_functor_ref(const manager_storage_type &storage) FUNC_NOEXCEPT
static Result call(const functor_padding &storage, Arguments...arguments)
const std::type_info &(*const call_type_id)()
First_Argument first_argument_type
static void move_functor(manager_storage_type &lhs, manager_storage_type &&rhs) FUNC_NOEXCEPT
#define FUNC_FORWARD(type, value)
void(*const call_copy_functor_only)(manager_storage_type &lhs, const manager_storage_type &rhs)
static std::allocator_traits< Allocator >::pointer & get_functor_ptr_ref(manager_storage_type &storage) FUNC_NOEXCEPT
Result empty_call(const functor_padding &, Arguments...)
bool operator==(std::nullptr_t, const function< T > &rhs) FUNC_NOEXCEPT
void initialize(T functor, Allocator &&allocator)
void initialize_empty() FUNC_NOEXCEPT
auto to_functor(Result(Class::*func)(Arguments...)) -> decltype(std::mem_fn(func))
static void templated_call_destroy(manager_storage_type &self)
const char * what() const FUNC_NOEXCEPT override
void swap(function< T > &lhs, function< T > &rhs)
bool is_null(Result(Class::*const &function_pointer)(Arguments...))