Files
gcc/libstdc++-v3/include/bits/std_function.h
Jason Merrill 63a598deb0 libstdc++: #ifdef out #pragma GCC system_header
In r15-3714-gd3a7302ec5985a I added -Wsystem-headers to the libstdc++ build
flags to help catch problems in the library.  This patch takes a different
approach, of disabling the #pragma system_header unless _GLIBCXX_SYSHDR is
defined.  As a result, the testsuites will treat them as non-system-headers
to get better warning coverage during regression testing of both gcc and
libstdc++, not just when building the library.

My rationale for the #ifdef instead of just removing the #pragma is the
three G++ tests that want to test libstdc++ system header behavior, so we
need a way to select it.

This doesn't affect installed libraries, as they get their
system-header status from the lookup path.  But testsuite_flags
--build-includes gives -I directives rather than -isystem.

This patch doesn't change the headers in config/ because I'm not compiling
with most of them, so won't see any warnings that need fixing.  Adjusting
them could happen later, or we can not bother.

libstdc++-v3/ChangeLog:

	* acinclude.m4 (WARN_FLAGS): Remove -Wsystem-headers.
	* configure: Regenerate.
	* include/bits/algorithmfwd.h: #ifdef out #pragma GCC system_header.
	* include/bits/atomic_base.h
	* include/bits/atomic_futex.h
	* include/bits/atomic_timed_wait.h
	* include/bits/atomic_wait.h
	* include/bits/basic_ios.h
	* include/bits/basic_string.h
	* include/bits/boost_concept_check.h
	* include/bits/char_traits.h
	* include/bits/charconv.h
	* include/bits/chrono.h
	* include/bits/chrono_io.h
	* include/bits/codecvt.h
	* include/bits/concept_check.h
	* include/bits/cpp_type_traits.h
	* include/bits/elements_of.h
	* include/bits/enable_special_members.h
	* include/bits/erase_if.h
	* include/bits/forward_list.h
	* include/bits/functional_hash.h
	* include/bits/gslice.h
	* include/bits/gslice_array.h
	* include/bits/hashtable.h
	* include/bits/indirect_array.h
	* include/bits/invoke.h
	* include/bits/ios_base.h
	* include/bits/iterator_concepts.h
	* include/bits/locale_classes.h
	* include/bits/locale_facets.h
	* include/bits/locale_facets_nonio.h
	* include/bits/localefwd.h
	* include/bits/mask_array.h
	* include/bits/max_size_type.h
	* include/bits/memory_resource.h
	* include/bits/memoryfwd.h
	* include/bits/move_only_function.h
	* include/bits/node_handle.h
	* include/bits/ostream_insert.h
	* include/bits/out_ptr.h
	* include/bits/parse_numbers.h
	* include/bits/postypes.h
	* include/bits/quoted_string.h
	* include/bits/range_access.h
	* include/bits/ranges_base.h
	* include/bits/refwrap.h
	* include/bits/sat_arith.h
	* include/bits/semaphore_base.h
	* include/bits/slice_array.h
	* include/bits/std_abs.h
	* include/bits/std_function.h
	* include/bits/std_mutex.h
	* include/bits/std_thread.h
	* include/bits/stl_iterator_base_funcs.h
	* include/bits/stl_iterator_base_types.h
	* include/bits/stl_tree.h
	* include/bits/stream_iterator.h
	* include/bits/streambuf_iterator.h
	* include/bits/stringfwd.h
	* include/bits/this_thread_sleep.h
	* include/bits/unique_lock.h
	* include/bits/uses_allocator_args.h
	* include/bits/utility.h
	* include/bits/valarray_after.h
	* include/bits/valarray_array.h
	* include/bits/valarray_before.h
	* include/bits/version.h
	* include/c_compatibility/fenv.h
	* include/c_compatibility/inttypes.h
	* include/c_compatibility/stdint.h
	* include/decimal/decimal.h
	* include/experimental/bits/net.h
	* include/experimental/bits/shared_ptr.h
	* include/ext/aligned_buffer.h
	* include/ext/alloc_traits.h
	* include/ext/atomicity.h
	* include/ext/concurrence.h
	* include/ext/numeric_traits.h
	* include/ext/pod_char_traits.h
	* include/ext/pointer.h
	* include/ext/stdio_filebuf.h
	* include/ext/stdio_sync_filebuf.h
	* include/ext/string_conversions.h
	* include/ext/type_traits.h
	* include/ext/vstring.h
	* include/ext/vstring_fwd.h
	* include/ext/vstring_util.h
	* include/parallel/algorithmfwd.h
	* include/parallel/numericfwd.h
	* include/tr1/functional_hash.h
	* include/tr1/hashtable.h
	* include/tr1/random.h
	* libsupc++/exception.h
	* libsupc++/hash_bytes.h
	* include/bits/basic_ios.tcc
	* include/bits/basic_string.tcc
	* include/bits/fstream.tcc
	* include/bits/istream.tcc
	* include/bits/locale_classes.tcc
	* include/bits/locale_facets.tcc
	* include/bits/locale_facets_nonio.tcc
	* include/bits/ostream.tcc
	* include/bits/sstream.tcc
	* include/bits/streambuf.tcc
	* include/bits/string_view.tcc
	* include/bits/version.tpl
	* include/experimental/bits/string_view.tcc
	* include/ext/pb_ds/detail/resize_policy/hash_prime_size_policy_imp.hpp
	* include/ext/random.tcc
	* include/ext/vstring.tcc
	* include/tr2/bool_set.tcc
	* include/tr2/dynamic_bitset.tcc
	* include/bits/c++config
	* include/c/cassert
	* include/c/cctype
	* include/c/cerrno
	* include/c/cfloat
	* include/c/ciso646
	* include/c/climits
	* include/c/clocale
	* include/c/cmath
	* include/c/csetjmp
	* include/c/csignal
	* include/c/cstdarg
	* include/c/cstddef
	* include/c/cstdio
	* include/c/cstdlib
	* include/c/cstring
	* include/c/ctime
	* include/c/cuchar
	* include/c/cwchar
	* include/c/cwctype
	* include/c_global/cassert
	* include/c_global/ccomplex
	* include/c_global/cctype
	* include/c_global/cerrno
	* include/c_global/cfenv
	* include/c_global/cfloat
	* include/c_global/cinttypes
	* include/c_global/ciso646
	* include/c_global/climits
	* include/c_global/clocale
	* include/c_global/cmath
	* include/c_global/csetjmp
	* include/c_global/csignal
	* include/c_global/cstdalign
	* include/c_global/cstdarg
	* include/c_global/cstdbool
	* include/c_global/cstddef
	* include/c_global/cstdint
	* include/c_global/cstdio
	* include/c_global/cstdlib
	* include/c_global/cstring
	* include/c_global/ctgmath
	* include/c_global/ctime
	* include/c_global/cuchar
	* include/c_global/cwchar
	* include/c_global/cwctype
	* include/c_std/cassert
	* include/c_std/cctype
	* include/c_std/cerrno
	* include/c_std/cfloat
	* include/c_std/ciso646
	* include/c_std/climits
	* include/c_std/clocale
	* include/c_std/cmath
	* include/c_std/csetjmp
	* include/c_std/csignal
	* include/c_std/cstdarg
	* include/c_std/cstddef
	* include/c_std/cstdio
	* include/c_std/cstdlib
	* include/c_std/cstring
	* include/c_std/ctime
	* include/c_std/cuchar
	* include/c_std/cwchar
	* include/c_std/cwctype
	* include/debug/array
	* include/debug/bitset
	* include/debug/deque
	* include/debug/forward_list
	* include/debug/list
	* include/debug/map
	* include/debug/set
	* include/debug/string
	* include/debug/unordered_map
	* include/debug/unordered_set
	* include/debug/vector
	* include/decimal/decimal
	* include/experimental/algorithm
	* include/experimental/any
	* include/experimental/array
	* include/experimental/buffer
	* include/experimental/chrono
	* include/experimental/contract
	* include/experimental/deque
	* include/experimental/executor
	* include/experimental/filesystem
	* include/experimental/forward_list
	* include/experimental/functional
	* include/experimental/internet
	* include/experimental/io_context
	* include/experimental/iterator
	* include/experimental/list
	* include/experimental/map
	* include/experimental/memory
	* include/experimental/memory_resource
	* include/experimental/net
	* include/experimental/netfwd
	* include/experimental/numeric
	* include/experimental/propagate_const
	* include/experimental/ratio
	* include/experimental/regex
	* include/experimental/scope
	* include/experimental/set
	* include/experimental/socket
	* include/experimental/string
	* include/experimental/string_view
	* include/experimental/synchronized_value
	* include/experimental/system_error
	* include/experimental/timer
	* include/experimental/tuple
	* include/experimental/type_traits
	* include/experimental/unordered_map
	* include/experimental/unordered_set
	* include/experimental/vector
	* include/ext/algorithm
	* include/ext/cmath
	* include/ext/functional
	* include/ext/iterator
	* include/ext/memory
	* include/ext/numeric
	* include/ext/random
	* include/ext/rb_tree
	* include/ext/rope
	* include/parallel/algorithm
	* include/std/algorithm
	* include/std/any
	* include/std/array
	* include/std/atomic
	* include/std/barrier
	* include/std/bit
	* include/std/bitset
	* include/std/charconv
	* include/std/chrono
	* include/std/codecvt
	* include/std/complex
	* include/std/concepts
	* include/std/condition_variable
	* include/std/coroutine
	* include/std/deque
	* include/std/execution
	* include/std/expected
	* include/std/filesystem
	* include/std/format
	* include/std/forward_list
	* include/std/fstream
	* include/std/functional
	* include/std/future
	* include/std/generator
	* include/std/iomanip
	* include/std/ios
	* include/std/iosfwd
	* include/std/iostream
	* include/std/istream
	* include/std/iterator
	* include/std/latch
	* include/std/limits
	* include/std/list
	* include/std/locale
	* include/std/map
	* include/std/memory
	* include/std/memory_resource
	* include/std/mutex
	* include/std/numbers
	* include/std/numeric
	* include/std/optional
	* include/std/ostream
	* include/std/print
	* include/std/queue
	* include/std/random
	* include/std/ranges
	* include/std/ratio
	* include/std/regex
	* include/std/scoped_allocator
	* include/std/semaphore
	* include/std/set
	* include/std/shared_mutex
	* include/std/span
	* include/std/spanstream
	* include/std/sstream
	* include/std/stack
	* include/std/stacktrace
	* include/std/stdexcept
	* include/std/streambuf
	* include/std/string
	* include/std/string_view
	* include/std/syncstream
	* include/std/system_error
	* include/std/text_encoding
	* include/std/thread
	* include/std/tuple
	* include/std/type_traits
	* include/std/typeindex
	* include/std/unordered_map
	* include/std/unordered_set
	* include/std/utility
	* include/std/valarray
	* include/std/variant
	* include/std/vector
	* include/std/version
	* include/tr1/array
	* include/tr1/cfenv
	* include/tr1/cinttypes
	* include/tr1/cmath
	* include/tr1/complex
	* include/tr1/cstdbool
	* include/tr1/cstdint
	* include/tr1/cstdio
	* include/tr1/cstdlib
	* include/tr1/cwchar
	* include/tr1/cwctype
	* include/tr1/functional
	* include/tr1/memory
	* include/tr1/random
	* include/tr1/regex
	* include/tr1/tuple
	* include/tr1/type_traits
	* include/tr1/unordered_map
	* include/tr1/unordered_set
	* include/tr1/utility
	* include/tr2/bool_set
	* include/tr2/dynamic_bitset
	* include/tr2/type_traits
	* libsupc++/atomic_lockfree_defines.h
	* libsupc++/compare
	* libsupc++/cxxabi.h
	* libsupc++/cxxabi_forced.h
	* libsupc++/cxxabi_init_exception.h
	* libsupc++/exception
	* libsupc++/initializer_list
	* libsupc++/new
	* libsupc++/typeinfo: Likewise.
	* testsuite/20_util/ratio/operations/ops_overflow_neg.cc
	* testsuite/23_containers/array/tuple_interface/get_neg.cc
	* testsuite/23_containers/vector/cons/destructible_debug_neg.cc
	* testsuite/24_iterators/operations/prev_neg.cc
	* testsuite/ext/type_traits/add_unsigned_floating_neg.cc
	* testsuite/ext/type_traits/add_unsigned_integer_neg.cc
	* testsuite/ext/type_traits/remove_unsigned_floating_neg.cc
	* testsuite/ext/type_traits/remove_unsigned_integer_neg.cc: Adjust
	line numbers.

gcc/testsuite/ChangeLog

	* g++.dg/analyzer/fanalyzer-show-events-in-system-headers-default.C
	* g++.dg/analyzer/fanalyzer-show-events-in-system-headers-no.C
	* g++.dg/diagnostic/disable.C: #define _GLIBCXX_SYSHDR.
2024-09-25 08:20:45 -04:00

808 lines
24 KiB
C++

// Implementation of std::function -*- C++ -*-
// Copyright (C) 2004-2024 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
#ifdef _GLIBCXX_SYSHDR
#pragma GCC system_header
#endif
#if __cplusplus < 201103L
# include <bits/c++0x_warning.h>
#else
#include <new> // placement new
#include <typeinfo> // typeid
#include <bits/invoke.h> // __invoke_r
#include <bits/refwrap.h> // ref wrapper, _Maybe_unary_or_binary_function
#include <bits/functexcept.h> // __throw_bad_function_call
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() noexcept { return &_M_pod_data[0]; }
const void* _M_access() const noexcept { return &_M_pod_data[0]; }
template<typename _Tp>
_Tp&
_M_access() noexcept
{ return *static_cast<_Tp*>(_M_access()); }
template<typename _Tp>
const _Tp&
_M_access() const noexcept
{ 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) noexcept
{
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) noexcept
{ return static_cast<bool>(__f); }
template<typename _Tp>
static bool
_M_not_empty_function(_Tp* __fp) noexcept
{ return __fp != nullptr; }
template<typename _Class, typename _Tp>
static bool
_M_not_empty_function(_Tp _Class::* __mp) noexcept
{ return __mp != nullptr; }
template<typename _Tp>
static bool
_M_not_empty_function(const _Tp&) noexcept
{ 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 `(bool)*this == (bool)x`
* @returns `*this`
*
* The target of `__x` is copied to `*this`. If `__x` has no
* target, then `*this` will be empty.
*
* If `__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 `*this`
*
* The target of `__x` is moved to `*this`. If `__x` has no
* target, then `*this` will be empty.
*
* If `__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 empty.
* @post `!(bool)*this`
* @returns `*this`
*
* The target of `*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 `_ArgTypes...` and returns a value convertible
* to `_Res`.
* @return `*this`
* @since C++11
*
* This function object wrapper 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 or null pointer-to-member, this 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.
*/
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 `this` function object and `__f`.
* This function will not throw exceptions.
*/
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 `true` when this function object contains a target,
* or `false` when it is empty.
*
* This function will not throw exceptions.
*/
explicit operator bool() const noexcept
{ return !_M_empty(); }
// [3.7.2.4] function invocation
/**
* @brief Invokes the function targeted by `*this`.
* @returns the result of the target.
* @throws `bad_function_call` when `!(bool)*this`
*
* The function call operator invokes the target function object
* stored by `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
* `typeid(void)` if `!(bool)*this`.
*
* This function will not throw exceptions.
*/
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 `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...); };
#if __cpp_explicit_this_parameter >= 202110L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 3617. function/packaged_task deduction guides and deducing this
template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
struct __function_guide_helper<_Res (*) (_Tp, _Args...) noexcept(_Nx)>
{ using type = _Res(_Args...); };
#endif
#if __cpp_static_call_operator >= 202207L && __cpp_concepts >= 202002L
template<typename _StaticCallOp>
struct __function_guide_static_helper
{ };
template<typename _Res, bool _Nx, typename... _Args>
struct __function_guide_static_helper<_Res (*) (_Args...) noexcept(_Nx)>
{ using type = _Res(_Args...); };
template<typename _Fn, typename _Op>
using __function_guide_t = typename __conditional_t<
requires (_Fn& __f) { (void) __f.operator(); },
__function_guide_static_helper<_Op>,
__function_guide_helper<_Op>>::type;
#else
template<typename _Fn, typename _Op>
using __function_guide_t = typename __function_guide_helper<_Op>::type;
#endif
template<typename _Res, typename... _ArgTypes>
function(_Res(*)(_ArgTypes...)) -> function<_Res(_ArgTypes...)>;
template<typename _Fn, typename _Signature
= __function_guide_t<_Fn, decltype(&_Fn::operator())>>
function(_Fn) -> function<_Signature>;
#endif
// [20.7.15.2.6] null pointer comparisons
/**
* @brief Test whether a polymorphic function object wrapper is empty.
* @returns `true` if the wrapper has no target, `false` otherwise
*
* This function will not throw exceptions.
*/
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 Test whether a polymorphic function object wrapper is non-empty.
* @returns `false` if the wrapper has no target, `true` otherwise
*
* This function will not throw exceptions.
*/
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 exceptions.
*/
// _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