You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

780 lines
22 KiB

3 years ago
// Implementation of std::function -*- C++ -*-
// Copyright (C) 2004-2021 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file include/bits/std_function.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{functional}
*/
#ifndef _GLIBCXX_STD_FUNCTION_H
#define _GLIBCXX_STD_FUNCTION_H 1
#pragma GCC system_header
#if __cplusplus < 201103L
# include <bits/c++0x_warning.h>
#else
#include <typeinfo>
#include <bits/stl_function.h>
#include <bits/invoke.h>
#include <bits/refwrap.h>
#include <bits/functexcept.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
/**
* @brief Exception class thrown when class template function's
* operator() is called with an empty target.
* @ingroup exceptions
*/
class bad_function_call : public std::exception
{
public:
virtual ~bad_function_call() noexcept;
const char* what() const noexcept;
};
/**
* Trait identifying "location-invariant" types, meaning that the
* address of the object (or any of its members) will not escape.
* Trivially copyable types are location-invariant and users can
* specialize this trait for other types.
*/
template<typename _Tp>
struct __is_location_invariant
: is_trivially_copyable<_Tp>::type
{ };
class _Undefined_class;
union _Nocopy_types
{
void* _M_object;
const void* _M_const_object;
void (*_M_function_pointer)();
void (_Undefined_class::*_M_member_pointer)();
};
union [[gnu::may_alias]] _Any_data
{
void* _M_access() { return &_M_pod_data[0]; }
const void* _M_access() const { return &_M_pod_data[0]; }
template<typename _Tp>
_Tp&
_M_access()
{ return *static_cast<_Tp*>(_M_access()); }
template<typename _Tp>
const _Tp&
_M_access() const
{ return *static_cast<const _Tp*>(_M_access()); }
_Nocopy_types _M_unused;
char _M_pod_data[sizeof(_Nocopy_types)];
};
enum _Manager_operation
{
__get_type_info,
__get_functor_ptr,
__clone_functor,
__destroy_functor
};
template<typename _Signature>
class function;
/// Base class of all polymorphic function object wrappers.
class _Function_base
{
public:
static const size_t _M_max_size = sizeof(_Nocopy_types);
static const size_t _M_max_align = __alignof__(_Nocopy_types);
template<typename _Functor>
class _Base_manager
{
protected:
static const bool __stored_locally =
(__is_location_invariant<_Functor>::value
&& sizeof(_Functor) <= _M_max_size
&& __alignof__(_Functor) <= _M_max_align
&& (_M_max_align % __alignof__(_Functor) == 0));
using _Local_storage = integral_constant<bool, __stored_locally>;
// Retrieve a pointer to the function object
static _Functor*
_M_get_pointer(const _Any_data& __source)
{
if _GLIBCXX17_CONSTEXPR (__stored_locally)
{
const _Functor& __f = __source._M_access<_Functor>();
return const_cast<_Functor*>(std::__addressof(__f));
}
else // have stored a pointer
return __source._M_access<_Functor*>();
}
private:
// Construct a location-invariant function object that fits within
// an _Any_data structure.
template<typename _Fn>
static void
_M_create(_Any_data& __dest, _Fn&& __f, true_type)
{
::new (__dest._M_access()) _Functor(std::forward<_Fn>(__f));
}
// Construct a function object on the heap and store a pointer.
template<typename _Fn>
static void
_M_create(_Any_data& __dest, _Fn&& __f, false_type)
{
__dest._M_access<_Functor*>()
= new _Functor(std::forward<_Fn>(__f));
}
// Destroy an object stored in the internal buffer.
static void
_M_destroy(_Any_data& __victim, true_type)
{
__victim._M_access<_Functor>().~_Functor();
}
// Destroy an object located on the heap.
static void
_M_destroy(_Any_data& __victim, false_type)
{
delete __victim._M_access<_Functor*>();
}
public:
static bool
_M_manager(_Any_data& __dest, const _Any_data& __source,
_Manager_operation __op)
{
switch (__op)
{
case __get_type_info:
#if __cpp_rtti
__dest._M_access<const type_info*>() = &typeid(_Functor);
#else
__dest._M_access<const type_info*>() = nullptr;
#endif
break;
case __get_functor_ptr:
__dest._M_access<_Functor*>() = _M_get_pointer(__source);
break;
case __clone_functor:
_M_init_functor(__dest,
*const_cast<const _Functor*>(_M_get_pointer(__source)));
break;
case __destroy_functor:
_M_destroy(__dest, _Local_storage());
break;
}
return false;
}
template<typename _Fn>
static void
_M_init_functor(_Any_data& __functor, _Fn&& __f)
noexcept(__and_<_Local_storage,
is_nothrow_constructible<_Functor, _Fn>>::value)
{
_M_create(__functor, std::forward<_Fn>(__f), _Local_storage());
}
template<typename _Signature>
static bool
_M_not_empty_function(const function<_Signature>& __f)
{ return static_cast<bool>(__f); }
template<typename _Tp>
static bool
_M_not_empty_function(_Tp* __fp)
{ return __fp != nullptr; }
template<typename _Class, typename _Tp>
static bool
_M_not_empty_function(_Tp _Class::* __mp)
{ return __mp != nullptr; }
template<typename _Tp>
static bool
_M_not_empty_function(const _Tp&)
{ return true; }
};
_Function_base() = default;
~_Function_base()
{
if (_M_manager)
_M_manager(_M_functor, _M_functor, __destroy_functor);
}
bool _M_empty() const { return !_M_manager; }
using _Manager_type
= bool (*)(_Any_data&, const _Any_data&, _Manager_operation);
_Any_data _M_functor{};
_Manager_type _M_manager{};
};
template<typename _Signature, typename _Functor>
class _Function_handler;
template<typename _Res, typename _Functor, typename... _ArgTypes>
class _Function_handler<_Res(_ArgTypes...), _Functor>
: public _Function_base::_Base_manager<_Functor>
{
using _Base = _Function_base::_Base_manager<_Functor>;
public:
static bool
_M_manager(_Any_data& __dest, const _Any_data& __source,
_Manager_operation __op)
{
switch (__op)
{
#if __cpp_rtti
case __get_type_info:
__dest._M_access<const type_info*>() = &typeid(_Functor);
break;
#endif
case __get_functor_ptr:
__dest._M_access<_Functor*>() = _Base::_M_get_pointer(__source);
break;
default:
_Base::_M_manager(__dest, __source, __op);
}
return false;
}
static _Res
_M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
{
return std::__invoke_r<_Res>(*_Base::_M_get_pointer(__functor),
std::forward<_ArgTypes>(__args)...);
}
template<typename _Fn>
static constexpr bool
_S_nothrow_init() noexcept
{
return __and_<typename _Base::_Local_storage,
is_nothrow_constructible<_Functor, _Fn>>::value;
}
};
// Specialization for invalid types
template<>
class _Function_handler<void, void>
{
public:
static bool
_M_manager(_Any_data&, const _Any_data&, _Manager_operation)
{ return false; }
};
// Avoids instantiating ill-formed specializations of _Function_handler
// in std::function<_Signature>::target<_Functor>().
// e.g. _Function_handler<Sig, void()> and _Function_handler<Sig, void>
// would be ill-formed.
template<typename _Signature, typename _Functor,
bool __valid = is_object<_Functor>::value>
struct _Target_handler
: _Function_handler<_Signature, typename remove_cv<_Functor>::type>
{ };
template<typename _Signature, typename _Functor>
struct _Target_handler<_Signature, _Functor, false>
: _Function_handler<void, void>
{ };
/**
* @brief Polymorphic function wrapper.
* @ingroup functors
* @since C++11
*/
template<typename _Res, typename... _ArgTypes>
class function<_Res(_ArgTypes...)>
: public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>,
private _Function_base
{
// Equivalent to std::decay_t except that it produces an invalid type
// if the decayed type is the current specialization of std::function.
template<typename _Func,
bool _Self = is_same<__remove_cvref_t<_Func>, function>::value>
using _Decay_t
= typename __enable_if_t<!_Self, decay<_Func>>::type;
template<typename _Func,
typename _DFunc = _Decay_t<_Func>,
typename _Res2 = __invoke_result<_DFunc&, _ArgTypes...>>
struct _Callable
: __is_invocable_impl<_Res2, _Res>::type
{ };
template<typename _Cond, typename _Tp = void>
using _Requires = __enable_if_t<_Cond::value, _Tp>;
template<typename _Functor>
using _Handler
= _Function_handler<_Res(_ArgTypes...), __decay_t<_Functor>>;
public:
typedef _Res result_type;
// [3.7.2.1] construct/copy/destroy
/**
* @brief Default construct creates an empty function call wrapper.
* @post `!(bool)*this`
*/
function() noexcept
: _Function_base() { }
/**
* @brief Creates an empty function call wrapper.
* @post @c !(bool)*this
*/
function(nullptr_t) noexcept
: _Function_base() { }
/**
* @brief %Function copy constructor.
* @param __x A %function object with identical call signature.
* @post `bool(*this) == bool(__x)`
*
* The newly-created %function contains a copy of the target of
* `__x` (if it has one).
*/
function(const function& __x)
: _Function_base()
{
if (static_cast<bool>(__x))
{
__x._M_manager(_M_functor, __x._M_functor, __clone_functor);
_M_invoker = __x._M_invoker;
_M_manager = __x._M_manager;
}
}
/**
* @brief %Function move constructor.
* @param __x A %function object rvalue with identical call signature.
*
* The newly-created %function contains the target of `__x`
* (if it has one).
*/
function(function&& __x) noexcept
: _Function_base(), _M_invoker(__x._M_invoker)
{
if (static_cast<bool>(__x))
{
_M_functor = __x._M_functor;
_M_manager = __x._M_manager;
__x._M_manager = nullptr;
__x._M_invoker = nullptr;
}
}
/**
* @brief Builds a %function that targets a copy of the incoming
* function object.
* @param __f A %function object that is callable with parameters of
* type `ArgTypes...` and returns a value convertible to `Res`.
*
* The newly-created %function object will target a copy of
* `__f`. If `__f` is `reference_wrapper<F>`, then this function
* object will contain a reference to the function object `__f.get()`.
* If `__f` is a null function pointer, null pointer-to-member, or
* empty `std::function`, the newly-created object will be empty.
*
* If `__f` is a non-null function pointer or an object of type
* `reference_wrapper<F>`, this function will not throw.
*/
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2774. std::function construction vs assignment
template<typename _Functor,
typename _Constraints = _Requires<_Callable<_Functor>>>
function(_Functor&& __f)
noexcept(_Handler<_Functor>::template _S_nothrow_init<_Functor>())
: _Function_base()
{
static_assert(is_copy_constructible<__decay_t<_Functor>>::value,
"std::function target must be copy-constructible");
static_assert(is_constructible<__decay_t<_Functor>, _Functor>::value,
"std::function target must be constructible from the "
"constructor argument");
using _My_handler = _Handler<_Functor>;
if (_My_handler::_M_not_empty_function(__f))
{
_My_handler::_M_init_functor(_M_functor,
std::forward<_Functor>(__f));
_M_invoker = &_My_handler::_M_invoke;
_M_manager = &_My_handler::_M_manager;
}
}
/**
* @brief %Function assignment operator.
* @param __x A %function with identical call signature.
* @post @c (bool)*this == (bool)x
* @returns @c *this
*
* The target of @a __x is copied to @c *this. If @a __x has no
* target, then @c *this will be empty.
*
* If @a __x targets a function pointer or a reference to a function
* object, then this operation will not throw an %exception.
*/
function&
operator=(const function& __x)
{
function(__x).swap(*this);
return *this;
}
/**
* @brief %Function move-assignment operator.
* @param __x A %function rvalue with identical call signature.
* @returns @c *this
*
* The target of @a __x is moved to @c *this. If @a __x has no
* target, then @c *this will be empty.
*
* If @a __x targets a function pointer or a reference to a function
* object, then this operation will not throw an %exception.
*/
function&
operator=(function&& __x) noexcept
{
function(std::move(__x)).swap(*this);
return *this;
}
/**
* @brief %Function assignment to zero.
* @post @c !(bool)*this
* @returns @c *this
*
* The target of @c *this is deallocated, leaving it empty.
*/
function&
operator=(nullptr_t) noexcept
{
if (_M_manager)
{
_M_manager(_M_functor, _M_functor, __destroy_functor);
_M_manager = nullptr;
_M_invoker = nullptr;
}
return *this;
}
/**
* @brief %Function assignment to a new target.
* @param __f A %function object that is callable with parameters of
* type @c T1, @c T2, ..., @c TN and returns a value convertible
* to @c Res.
* @return @c *this
*
* This %function object wrapper will target a copy of @a
* __f. If @a __f is @c reference_wrapper<F>, then this function
* object will contain a reference to the function object @c
* __f.get(). If @a __f is a NULL function pointer or NULL
* pointer-to-member, @c this object will be empty.
*
* If @a __f is a non-NULL function pointer or an object of type @c
* reference_wrapper<F>, this function will not throw.
*/
template<typename _Functor>
_Requires<_Callable<_Functor>, function&>
operator=(_Functor&& __f)
noexcept(_Handler<_Functor>::template _S_nothrow_init<_Functor>())
{
function(std::forward<_Functor>(__f)).swap(*this);
return *this;
}
/// @overload
template<typename _Functor>
function&
operator=(reference_wrapper<_Functor> __f) noexcept
{
function(__f).swap(*this);
return *this;
}
// [3.7.2.2] function modifiers
/**
* @brief Swap the targets of two %function objects.
* @param __x A %function with identical call signature.
*
* Swap the targets of @c this function object and @a __f. This
* function will not throw an %exception.
*/
void swap(function& __x) noexcept
{
std::swap(_M_functor, __x._M_functor);
std::swap(_M_manager, __x._M_manager);
std::swap(_M_invoker, __x._M_invoker);
}
// [3.7.2.3] function capacity
/**
* @brief Determine if the %function wrapper has a target.
*
* @return @c true when this %function object contains a target,
* or @c false when it is empty.
*
* This function will not throw an %exception.
*/
explicit operator bool() const noexcept
{ return !_M_empty(); }
// [3.7.2.4] function invocation
/**
* @brief Invokes the function targeted by @c *this.
* @returns the result of the target.
* @throws bad_function_call when @c !(bool)*this
*
* The function call operator invokes the target function object
* stored by @c this.
*/
_Res
operator()(_ArgTypes... __args) const
{
if (_M_empty())
__throw_bad_function_call();
return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
}
#if __cpp_rtti
// [3.7.2.5] function target access
/**
* @brief Determine the type of the target of this function object
* wrapper.
*
* @returns the type identifier of the target function object, or
* @c typeid(void) if @c !(bool)*this.
*
* This function will not throw an %exception.
*/
const type_info&
target_type() const noexcept
{
if (_M_manager)
{
_Any_data __typeinfo_result;
_M_manager(__typeinfo_result, _M_functor, __get_type_info);
if (auto __ti = __typeinfo_result._M_access<const type_info*>())
return *__ti;
}
return typeid(void);
}
#endif
/**
* @brief Access the stored target function object.
*
* @return Returns a pointer to the stored target function object,
* if @c typeid(_Functor).equals(target_type()); otherwise, a null
* pointer.
*
* This function does not throw exceptions.
*
* @{
*/
template<typename _Functor>
_Functor*
target() noexcept
{
const function* __const_this = this;
const _Functor* __func = __const_this->template target<_Functor>();
// If is_function_v<_Functor> is true then const_cast<_Functor*>
// would be ill-formed, so use *const_cast<_Functor**> instead.
return *const_cast<_Functor**>(&__func);
}
template<typename _Functor>
const _Functor*
target() const noexcept
{
if _GLIBCXX17_CONSTEXPR (is_object<_Functor>::value)
{
// For C++11 and C++14 if-constexpr is not used above, so
// _Target_handler avoids ill-formed _Function_handler types.
using _Handler = _Target_handler<_Res(_ArgTypes...), _Functor>;
if (_M_manager == &_Handler::_M_manager
#if __cpp_rtti
|| (_M_manager && typeid(_Functor) == target_type())
#endif
)
{
_Any_data __ptr;
_M_manager(__ptr, _M_functor, __get_functor_ptr);
return __ptr._M_access<const _Functor*>();
}
}
return nullptr;
}
/// @}
private:
using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...);
_Invoker_type _M_invoker = nullptr;
};
#if __cpp_deduction_guides >= 201606
template<typename>
struct __function_guide_helper
{ };
template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
struct __function_guide_helper<
_Res (_Tp::*) (_Args...) noexcept(_Nx)
>
{ using type = _Res(_Args...); };
template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
struct __function_guide_helper<
_Res (_Tp::*) (_Args...) & noexcept(_Nx)
>
{ using type = _Res(_Args...); };
template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
struct __function_guide_helper<
_Res (_Tp::*) (_Args...) const noexcept(_Nx)
>
{ using type = _Res(_Args...); };
template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
struct __function_guide_helper<
_Res (_Tp::*) (_Args...) const & noexcept(_Nx)
>
{ using type = _Res(_Args...); };
template<typename _Res, typename... _ArgTypes>
function(_Res(*)(_ArgTypes...)) -> function<_Res(_ArgTypes...)>;
template<typename _Functor, typename _Signature = typename
__function_guide_helper<decltype(&_Functor::operator())>::type>
function(_Functor) -> function<_Signature>;
#endif
// [20.7.15.2.6] null pointer comparisons
/**
* @brief Compares a polymorphic function object wrapper against 0
* (the NULL pointer).
* @returns @c true if the wrapper has no target, @c false otherwise
*
* This function will not throw an %exception.
*/
template<typename _Res, typename... _Args>
inline bool
operator==(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
{ return !static_cast<bool>(__f); }
#if __cpp_impl_three_way_comparison < 201907L
/// @overload
template<typename _Res, typename... _Args>
inline bool
operator==(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
{ return !static_cast<bool>(__f); }
/**
* @brief Compares a polymorphic function object wrapper against 0
* (the NULL pointer).
* @returns @c false if the wrapper has no target, @c true otherwise
*
* This function will not throw an %exception.
*/
template<typename _Res, typename... _Args>
inline bool
operator!=(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
{ return static_cast<bool>(__f); }
/// @overload
template<typename _Res, typename... _Args>
inline bool
operator!=(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
{ return static_cast<bool>(__f); }
#endif
// [20.7.15.2.7] specialized algorithms
/**
* @brief Swap the targets of two polymorphic function object wrappers.
*
* This function will not throw an %exception.
*/
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2062. Effect contradictions w/o no-throw guarantee of std::function swaps
template<typename _Res, typename... _Args>
inline void
swap(function<_Res(_Args...)>& __x, function<_Res(_Args...)>& __y) noexcept
{ __x.swap(__y); }
#if __cplusplus >= 201703L
namespace __detail::__variant
{
template<typename> struct _Never_valueless_alt; // see <variant>
// Provide the strong exception-safety guarantee when emplacing a
// function into a variant.
template<typename _Signature>
struct _Never_valueless_alt<std::function<_Signature>>
: std::true_type
{ };
} // namespace __detail::__variant
#endif // C++17
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++11
#endif // _GLIBCXX_STD_FUNCTION_H