mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 12:00:03 -05:00
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.
808 lines
24 KiB
C++
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
|