aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Kamiński <tkaminsk@redhat.com>2025-09-01 14:28:17 +0200
committerTomasz Kamiński <tkaminsk@redhat.com>2025-09-04 15:29:36 +0200
commitb2adb7712cc57920d7d791c185dbf88e83b885c2 (patch)
tree66471c920f4bf6d953c9c50ea54eb3c70cfeb8e4
parent2c2df024df3aa6248f92203df9c1051b5f1fe5f8 (diff)
downloadgcc-b2adb7712cc57920d7d791c185dbf88e83b885c2.zip
gcc-b2adb7712cc57920d7d791c185dbf88e83b885c2.tar.gz
gcc-b2adb7712cc57920d7d791c185dbf88e83b885c2.tar.bz2
libstdc++: Move _Binder and related aliases to separate file.
bits/binders.h is already mapped in libstdc++-v3/doc/doxygen/stdheader.cc. libstdc++-v3/ChangeLog: * include/Makefile.am: Add bits/binders.h * include/Makefile.in: Add bits/binders.h * include/std/functional (std::_Indexed_bound_arg, std::_Binder) (std::__make_bound_args, std::_Bind_front_t, std::_Bind_back_t): Moved to bits/binders.h file, that is now included. * include/bits/binders.h: New file. Reviewed-by: Patrick Palka <ppalka@redhat.com> Reviewed-by: Jonathan Wakely <jwakely@redhat.com> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
-rw-r--r--libstdc++-v3/include/Makefile.am1
-rw-r--r--libstdc++-v3/include/Makefile.in1
-rw-r--r--libstdc++-v3/include/bits/binders.h234
-rw-r--r--libstdc++-v3/include/std/functional187
4 files changed, 237 insertions, 186 deletions
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 6f59469..0b0cbe2 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -191,6 +191,7 @@ bits_headers = \
${bits_srcdir}/basic_ios.tcc \
${bits_srcdir}/basic_string.h \
${bits_srcdir}/basic_string.tcc \
+ ${bits_srcdir}/binders.h \
${bits_srcdir}/charconv.h \
${bits_srcdir}/chrono.h \
${bits_srcdir}/chrono_io.h \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 4b5917e..e3a6d5f 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -544,6 +544,7 @@ bits_freestanding = \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/basic_ios.tcc \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/basic_string.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/basic_string.tcc \
+@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/binders.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/charconv.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/chrono.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/chrono_io.h \
diff --git a/libstdc++-v3/include/bits/binders.h b/libstdc++-v3/include/bits/binders.h
new file mode 100644
index 0000000..c324bf5
--- /dev/null
+++ b/libstdc++-v3/include/bits/binders.h
@@ -0,0 +1,234 @@
+// Implementation of std::move_only_function, std::copyable_function
+// and std::function_ref -*- C++ -*-
+
+// Copyright The GNU Toolchain Authors.
+//
+// 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/binder.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{functional}
+ */
+
+#ifndef _GLIBCXX_BINDERS_H
+#define _GLIBCXX_BINDERS_H 1
+
+#ifdef _GLIBCXX_SYSHDR
+#pragma GCC system_header
+#endif
+
+#if __cplusplus >= 202002L
+
+#include <bits/invoke.h>
+#include <bits/move.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<size_t, typename _Tp>
+ struct _Indexed_bound_arg
+ {
+ [[no_unique_address]] _Tp _M_val;
+ };
+
+ template<typename... _IndexedArgs>
+ struct _Bound_arg_storage : _IndexedArgs...
+ {
+ template<bool _Back, typename _Fd, typename _Self, typename... _CallArgs>
+ static constexpr
+ decltype(auto)
+ _S_apply(_Fd&& __fd, _Self&& __self, _CallArgs&&... __call_args)
+ {
+ if constexpr (_Back)
+ return std::__invoke(std::forward<_Fd>(__fd),
+ std::forward<_CallArgs>(__call_args)...,
+ __like_t<_Self, _IndexedArgs>(__self)._M_val...);
+ else
+ return std::__invoke(std::forward<_Fd>(__fd),
+ __like_t<_Self, _IndexedArgs>(__self)._M_val...,
+ std::forward<_CallArgs>(__call_args)...);
+ }
+ };
+
+ template<typename... _BoundArgs, typename... _Args>
+ constexpr auto
+ __make_bound_args(_Args&&... __args)
+ {
+ if constexpr (sizeof...(_BoundArgs) == 1)
+ // pack has one element, so return copy of arg
+ return (_BoundArgs(std::forward<_Args>(__args)), ...);
+ else
+ {
+ auto __impl = [&]<size_t... _Inds>(index_sequence<_Inds...>)
+ {
+ return _Bound_arg_storage<_Indexed_bound_arg<_Inds, _BoundArgs>...>
+ { {_BoundArgs(std::forward<_Args>(__args))}... };
+ };
+ return __impl(index_sequence_for<_BoundArgs...>());
+ }
+ }
+
+ template<bool _Back, typename _Fd, typename... _BoundArgs>
+ class _Binder
+ {
+ template<typename _Self, typename... _CallArgs>
+ using _Result_t = __conditional_t<
+ _Back,
+ invoke_result<__like_t<_Self, _Fd>,
+ _CallArgs..., __like_t<_Self, _BoundArgs>...>,
+ invoke_result<__like_t<_Self, _Fd>,
+ __like_t<_Self, _BoundArgs>..., _CallArgs...>>::type;
+
+ template<typename _Self, typename... _CallArgs>
+ static consteval bool
+ _S_noexcept_invocable()
+ {
+ if constexpr (_Back)
+ return is_nothrow_invocable_v< __like_t<_Self, _Fd>,
+ _CallArgs..., __like_t<_Self, _BoundArgs>...>;
+ else
+ return is_nothrow_invocable_v<__like_t<_Self, _Fd>,
+ __like_t<_Self, _BoundArgs>..., _CallArgs...>;
+ }
+
+ public:
+ static_assert(is_move_constructible_v<_Fd>);
+ static_assert((is_move_constructible_v<_BoundArgs> && ...));
+
+ // First parameter is to ensure this constructor is never used
+ // instead of the copy/move constructor.
+ template<typename _Fn, typename... _Args>
+ explicit constexpr
+ _Binder(int, _Fn&& __fn, _Args&&... __args)
+ noexcept(__and_<is_nothrow_constructible<_Fd, _Fn>,
+ is_nothrow_constructible<_BoundArgs, _Args>...>::value)
+ : _M_fd(std::forward<_Fn>(__fn)),
+ _M_bound_args(__make_bound_args<_BoundArgs...>(std::forward<_Args>(__args)...))
+ { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); }
+
+#if __cpp_explicit_this_parameter
+ template<typename _Self, typename... _CallArgs>
+ constexpr _Result_t<_Self, _CallArgs...>
+ operator()(this _Self&& __self, _CallArgs&&... __call_args)
+ noexcept(_S_noexcept_invocable<_Self, _CallArgs...>())
+ {
+ return _S_call(__like_t<_Self, _Binder>(__self),
+ std::forward<_CallArgs>(__call_args)...);
+ }
+#else
+ template<typename... _CallArgs>
+ requires true
+ constexpr _Result_t<_Binder&, _CallArgs...>
+ operator()(_CallArgs&&... __call_args) &
+ noexcept(_S_noexcept_invocable<_Binder&, _CallArgs...>())
+ {
+ return _S_call(*this, std::forward<_CallArgs>(__call_args)...);
+ }
+
+ template<typename... _CallArgs>
+ requires true
+ constexpr _Result_t<const _Binder&, _CallArgs...>
+ operator()(_CallArgs&&... __call_args) const &
+ noexcept(_S_noexcept_invocable<const _Binder&, _CallArgs...>())
+ {
+ return _S_call(*this, std::forward<_CallArgs>(__call_args)...);
+ }
+
+ template<typename... _CallArgs>
+ requires true
+ constexpr _Result_t<_Binder&&, _CallArgs...>
+ operator()(_CallArgs&&... __call_args) &&
+ noexcept(_S_noexcept_invocable<_Binder&&, _CallArgs...>())
+ {
+ return _S_call(std::move(*this),
+ std::forward<_CallArgs>(__call_args)...);
+ }
+
+ template<typename... _CallArgs>
+ requires true
+ constexpr _Result_t<const _Binder&&, _CallArgs...>
+ operator()(_CallArgs&&... __call_args) const &&
+ noexcept(_S_noexcept_invocable<const _Binder&&, _CallArgs...>())
+ {
+ return _S_call(std::move(*this),
+ std::forward<_CallArgs>(__call_args)...);
+ }
+
+ template<typename... _CallArgs>
+ void operator()(_CallArgs&&...) & = delete;
+
+ template<typename... _CallArgs>
+ void operator()(_CallArgs&&...) const & = delete;
+
+ template<typename... _CallArgs>
+ void operator()(_CallArgs&&...) && = delete;
+
+ template<typename... _CallArgs>
+ void operator()(_CallArgs&&...) const && = delete;
+#endif
+
+ private:
+ using _BoundArgsStorage
+ // _BoundArgs are required to be move-constructible, so this is valid.
+ = decltype(__make_bound_args<_BoundArgs...>(std::declval<_BoundArgs>()...));
+
+ template<typename _Tp, typename... _CallArgs>
+ static constexpr
+ decltype(auto)
+ _S_call(_Tp&& __g, _CallArgs&&... __call_args)
+ {
+ if constexpr (sizeof...(_BoundArgs) > 1)
+ return _BoundArgsStorage::template _S_apply<_Back>(
+ std::forward<_Tp>(__g)._M_fd,
+ std::forward<_Tp>(__g)._M_bound_args,
+ std::forward<_CallArgs>(__call_args)...);
+ else if constexpr (sizeof...(_BoundArgs) == 0)
+ return std::__invoke(std::forward<_Tp>(__g)._M_fd,
+ std::forward<_CallArgs>(__call_args)...);
+ else if constexpr (_Back) // sizeof...(_BoundArgs) == 1
+ return std::__invoke(std::forward<_Tp>(__g)._M_fd,
+ std::forward<_CallArgs>(__call_args)...,
+ std::forward<_Tp>(__g)._M_bound_args);
+ else // !_Back && sizeof...(_BoundArgs) == 1
+ return std::__invoke(std::forward<_Tp>(__g)._M_fd,
+ std::forward<_Tp>(__g)._M_bound_args,
+ std::forward<_CallArgs>(__call_args)...);
+ }
+
+ [[no_unique_address]] _Fd _M_fd;
+ [[no_unique_address]] _BoundArgsStorage _M_bound_args;
+ };
+
+ template<typename _Fn, typename... _Args>
+ using _Bind_front_t = _Binder<false, decay_t<_Fn>, decay_t<_Args>...>;
+
+ // for zero bounds args behavior of bind_front and bind_back is the same,
+ // so reuse _Bind_front_t, i.e. _Binder<false, ...>
+ template<typename _Fn, typename... _Args>
+ using _Bind_back_t
+ = _Binder<(sizeof...(_Args) > 0), decay_t<_Fn>, decay_t<_Args>...>;
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // __cplusplus >= 202002L
+#endif // _GLIBCXX_BINDERS_H
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index ad23976..5b329da 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -84,6 +84,7 @@
# include <bits/stl_algobase.h> // std::search
#endif
#if __cplusplus >= 202002L
+# include <bits/binders.h>
# include <bits/ranges_cmp.h> // std::identity, ranges::equal_to etc.
# include <compare>
#endif
@@ -921,192 +922,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::forward<_BoundArgs>(__args)...);
}
-#if __cplusplus >= 202002L
- template<size_t, typename _Tp>
- struct _Indexed_bound_arg
- {
- [[no_unique_address]] _Tp _M_val;
- };
-
- template<typename... _IndexedArgs>
- struct _Bound_arg_storage : _IndexedArgs...
- {
- template<bool _Back, typename _Fd, typename _Self, typename... _CallArgs>
- static constexpr
- decltype(auto)
- _S_apply(_Fd&& __fd, _Self&& __self, _CallArgs&&... __call_args)
- {
- if constexpr (_Back)
- return std::__invoke(std::forward<_Fd>(__fd),
- std::forward<_CallArgs>(__call_args)...,
- __like_t<_Self, _IndexedArgs>(__self)._M_val...);
- else
- return std::__invoke(std::forward<_Fd>(__fd),
- __like_t<_Self, _IndexedArgs>(__self)._M_val...,
- std::forward<_CallArgs>(__call_args)...);
- }
- };
-
- template<typename... _BoundArgs, typename... _Args>
- constexpr auto
- __make_bound_args(_Args&&... __args)
- {
- if constexpr (sizeof...(_BoundArgs) == 1)
- // pack has one element, so return copy of arg
- return (_BoundArgs(std::forward<_Args>(__args)), ...);
- else
- {
- auto __impl = [&]<size_t... _Inds>(index_sequence<_Inds...>)
- {
- return _Bound_arg_storage<_Indexed_bound_arg<_Inds, _BoundArgs>...>
- { {_BoundArgs(std::forward<_Args>(__args))}... };
- };
- return __impl(index_sequence_for<_BoundArgs...>());
- }
- }
-
- template<bool _Back, typename _Fd, typename... _BoundArgs>
- class _Binder
- {
- template<typename _Self, typename... _CallArgs>
- using _Result_t = __conditional_t<
- _Back,
- invoke_result<__like_t<_Self, _Fd>,
- _CallArgs..., __like_t<_Self, _BoundArgs>...>,
- invoke_result<__like_t<_Self, _Fd>,
- __like_t<_Self, _BoundArgs>..., _CallArgs...>>::type;
-
- template<typename _Self, typename... _CallArgs>
- static consteval bool
- _S_noexcept_invocable()
- {
- if constexpr (_Back)
- return is_nothrow_invocable_v< __like_t<_Self, _Fd>,
- _CallArgs..., __like_t<_Self, _BoundArgs>...>;
- else
- return is_nothrow_invocable_v<__like_t<_Self, _Fd>,
- __like_t<_Self, _BoundArgs>..., _CallArgs...>;
- }
-
- public:
- static_assert(is_move_constructible_v<_Fd>);
- static_assert((is_move_constructible_v<_BoundArgs> && ...));
-
- // First parameter is to ensure this constructor is never used
- // instead of the copy/move constructor.
- template<typename _Fn, typename... _Args>
- explicit constexpr
- _Binder(int, _Fn&& __fn, _Args&&... __args)
- noexcept(__and_<is_nothrow_constructible<_Fd, _Fn>,
- is_nothrow_constructible<_BoundArgs, _Args>...>::value)
- : _M_fd(std::forward<_Fn>(__fn)),
- _M_bound_args(__make_bound_args<_BoundArgs...>(std::forward<_Args>(__args)...))
- { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); }
-
-#if __cpp_explicit_this_parameter
- template<typename _Self, typename... _CallArgs>
- constexpr _Result_t<_Self, _CallArgs...>
- operator()(this _Self&& __self, _CallArgs&&... __call_args)
- noexcept(_S_noexcept_invocable<_Self, _CallArgs...>())
- {
- return _S_call(__like_t<_Self, _Binder>(__self),
- std::forward<_CallArgs>(__call_args)...);
- }
-#else
- template<typename... _CallArgs>
- requires true
- constexpr _Result_t<_Binder&, _CallArgs...>
- operator()(_CallArgs&&... __call_args) &
- noexcept(_S_noexcept_invocable<_Binder&, _CallArgs...>())
- {
- return _S_call(*this, std::forward<_CallArgs>(__call_args)...);
- }
-
- template<typename... _CallArgs>
- requires true
- constexpr _Result_t<const _Binder&, _CallArgs...>
- operator()(_CallArgs&&... __call_args) const &
- noexcept(_S_noexcept_invocable<const _Binder&, _CallArgs...>())
- {
- return _S_call(*this, std::forward<_CallArgs>(__call_args)...);
- }
-
- template<typename... _CallArgs>
- requires true
- constexpr _Result_t<_Binder&&, _CallArgs...>
- operator()(_CallArgs&&... __call_args) &&
- noexcept(_S_noexcept_invocable<_Binder&&, _CallArgs...>())
- {
- return _S_call(std::move(*this),
- std::forward<_CallArgs>(__call_args)...);
- }
-
- template<typename... _CallArgs>
- requires true
- constexpr _Result_t<const _Binder&&, _CallArgs...>
- operator()(_CallArgs&&... __call_args) const &&
- noexcept(_S_noexcept_invocable<const _Binder&&, _CallArgs...>())
- {
- return _S_call(std::move(*this),
- std::forward<_CallArgs>(__call_args)...);
- }
-
- template<typename... _CallArgs>
- void operator()(_CallArgs&&...) & = delete;
-
- template<typename... _CallArgs>
- void operator()(_CallArgs&&...) const & = delete;
-
- template<typename... _CallArgs>
- void operator()(_CallArgs&&...) && = delete;
-
- template<typename... _CallArgs>
- void operator()(_CallArgs&&...) const && = delete;
-#endif
-
- private:
- using _BoundArgsStorage
- // _BoundArgs are required to be move-constructible, so this is valid.
- = decltype(__make_bound_args<_BoundArgs...>(std::declval<_BoundArgs>()...));
-
- template<typename _Tp, typename... _CallArgs>
- static constexpr
- decltype(auto)
- _S_call(_Tp&& __g, _CallArgs&&... __call_args)
- {
- if constexpr (sizeof...(_BoundArgs) > 1)
- return _BoundArgsStorage::template _S_apply<_Back>(
- std::forward<_Tp>(__g)._M_fd,
- std::forward<_Tp>(__g)._M_bound_args,
- std::forward<_CallArgs>(__call_args)...);
- else if constexpr (sizeof...(_BoundArgs) == 0)
- return std::__invoke(std::forward<_Tp>(__g)._M_fd,
- std::forward<_CallArgs>(__call_args)...);
- else if constexpr (_Back) // sizeof...(_BoundArgs) == 1
- return std::__invoke(std::forward<_Tp>(__g)._M_fd,
- std::forward<_CallArgs>(__call_args)...,
- std::forward<_Tp>(__g)._M_bound_args);
- else // !_Back && sizeof...(_BoundArgs) == 1
- return std::__invoke(std::forward<_Tp>(__g)._M_fd,
- std::forward<_Tp>(__g)._M_bound_args,
- std::forward<_CallArgs>(__call_args)...);
-
- }
-
- [[no_unique_address]] _Fd _M_fd;
- [[no_unique_address]] _BoundArgsStorage _M_bound_args;
- };
-
- template<typename _Fn, typename... _Args>
- using _Bind_front_t = _Binder<false, decay_t<_Fn>, decay_t<_Args>...>;
-
- // for zero bounds args behavior of bind_front and bind_back is the same,
- // so reuse _Bind_front_t, i.e. _Binder<false, ...>
- template<typename _Fn, typename... _Args>
- using _Bind_back_t
- = _Binder<(sizeof...(_Args) > 0), decay_t<_Fn>, decay_t<_Args>...>;
-#endif // __cplusplus >= 202002L
-
#ifdef __cpp_lib_bind_front // C++ >= 20
/** Create call wrapper by partial application of arguments to function.
*