aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r--libstdc++-v3/include/Makefile.am3
-rw-r--r--libstdc++-v3/include/Makefile.in3
-rw-r--r--libstdc++-v3/include/bits/cpyfunc_impl.h269
-rw-r--r--libstdc++-v3/include/bits/funcwrap.h507
-rw-r--r--libstdc++-v3/include/bits/mofunc_impl.h78
-rw-r--r--libstdc++-v3/include/bits/move_only_function.h218
-rw-r--r--libstdc++-v3/include/bits/version.def9
-rw-r--r--libstdc++-v3/include/bits/version.h10
-rw-r--r--libstdc++-v3/include/std/format217
-rw-r--r--libstdc++-v3/include/std/functional31
-rw-r--r--libstdc++-v3/include/std/utility2
11 files changed, 1011 insertions, 336 deletions
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 1140fa0..3e5b6c4 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -194,6 +194,7 @@ bits_headers = \
${bits_srcdir}/chrono_io.h \
${bits_srcdir}/codecvt.h \
${bits_srcdir}/cow_string.h \
+ ${bits_srcdir}/cpyfunc_impl.h \
${bits_srcdir}/deque.tcc \
${bits_srcdir}/erase_if.h \
${bits_srcdir}/formatfwd.h \
@@ -204,6 +205,7 @@ bits_headers = \
${bits_srcdir}/fs_ops.h \
${bits_srcdir}/fs_path.h \
${bits_srcdir}/fstream.tcc \
+ ${bits_srcdir}/funcwrap.h \
${bits_srcdir}/gslice.h \
${bits_srcdir}/gslice_array.h \
${bits_srcdir}/hashtable.h \
@@ -223,7 +225,6 @@ bits_headers = \
${bits_srcdir}/mask_array.h \
${bits_srcdir}/memory_resource.h \
${bits_srcdir}/mofunc_impl.h \
- ${bits_srcdir}/move_only_function.h \
${bits_srcdir}/new_allocator.h \
${bits_srcdir}/node_handle.h \
${bits_srcdir}/ostream.tcc \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index c96e981..3531162 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -547,6 +547,7 @@ bits_freestanding = \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/chrono_io.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/codecvt.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/cow_string.h \
+@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/cpyfunc_impl.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/deque.tcc \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/erase_if.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/formatfwd.h \
@@ -557,6 +558,7 @@ bits_freestanding = \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/fs_ops.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/fs_path.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/fstream.tcc \
+@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/funcwrap.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/gslice.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/gslice_array.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/hashtable.h \
@@ -576,7 +578,6 @@ bits_freestanding = \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/mask_array.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/memory_resource.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/mofunc_impl.h \
-@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/move_only_function.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/new_allocator.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/node_handle.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/ostream.tcc \
diff --git a/libstdc++-v3/include/bits/cpyfunc_impl.h b/libstdc++-v3/include/bits/cpyfunc_impl.h
new file mode 100644
index 0000000..bc44cd3e
--- /dev/null
+++ b/libstdc++-v3/include/bits/cpyfunc_impl.h
@@ -0,0 +1,269 @@
+// Implementation of std::copyable_function -*- 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/cpyfunc_impl.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{functional}
+ */
+
+#ifndef _GLIBCXX_MOF_CV
+# define _GLIBCXX_MOF_CV
+#endif
+
+#ifdef _GLIBCXX_MOF_REF
+# define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF
+#else
+# define _GLIBCXX_MOF_REF
+# define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV &
+#endif
+
+#define _GLIBCXX_MOF_CV_REF _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /**
+ * @brief Polymorphic copyable function wrapper.
+ * @ingroup functors
+ * @since C++26
+ * @headerfile functional
+ *
+ * The `std::copyable_function` class template is a call wrapper similar
+ * to `std::function`, but it does not provide information about it's
+ * target, and preserves constness.
+ *
+ * It also supports const-qualification, ref-qualification, and
+ * no-throw guarantees. The qualifications and exception-specification
+ * of the `copyable_function::operator()` member function are respected
+ * when invoking the target function.
+ */
+ template<typename _Res, typename... _ArgTypes, bool _Noex>
+ class copyable_function<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
+ _GLIBCXX_MOF_REF noexcept(_Noex)>
+ : __polyfunc::_Cpy_base
+ {
+ using _Base = __polyfunc::_Cpy_base;
+ using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>;
+ using _Signature = _Invoker::_Signature;
+
+ template<typename _Tp>
+ using __callable
+ = __conditional_t<_Noex,
+ is_nothrow_invocable_r<_Res, _Tp, _ArgTypes...>,
+ is_invocable_r<_Res, _Tp, _ArgTypes...>>;
+
+ // [func.wrap.copy.con]/1 is-callable-from<VT>
+ template<typename _Vt>
+ static constexpr bool __is_callable_from
+ = __and_v<__callable<_Vt _GLIBCXX_MOF_CV_REF>,
+ __callable<_Vt _GLIBCXX_MOF_INV_QUALS>>;
+
+ public:
+ using result_type = _Res;
+
+ /// Creates an empty object.
+ copyable_function() noexcept { }
+
+ /// Creates an empty object.
+ copyable_function(nullptr_t) noexcept { }
+
+ /// Moves the target object, leaving the source empty.
+ copyable_function(copyable_function&& __x) noexcept
+ : _Base(static_cast<_Base&&>(__x)),
+ _M_invoke(std::__exchange(__x._M_invoke, nullptr))
+ { }
+
+ /// Copies the target object.
+ copyable_function(copyable_function const& __x)
+ : _Base(static_cast<const _Base&>(__x)),
+ _M_invoke(__x._M_invoke)
+ { }
+
+ /// Stores a target object initialized from the argument.
+ template<typename _Fn, typename _Vt = decay_t<_Fn>>
+ requires (!is_same_v<_Vt, copyable_function>)
+ && (!__is_in_place_type_v<_Vt>) && __is_callable_from<_Vt>
+ copyable_function(_Fn&& __f) noexcept(_S_nothrow_init<_Vt, _Fn>())
+ {
+ static_assert(is_copy_constructible_v<_Vt>);
+ if constexpr (is_function_v<remove_pointer_t<_Vt>>
+ || is_member_pointer_v<_Vt>
+ || __is_polymorphic_function_v<_Vt>)
+ {
+ if (__f == nullptr)
+ return;
+ }
+
+ if constexpr (!__is_polymorphic_function_v<_Vt>
+ || !__polyfunc::__is_invoker_convertible<_Vt, copyable_function>())
+ {
+ _M_init<_Vt>(std::forward<_Fn>(__f));
+ _M_invoke = _Invoker::template _S_storage<_Vt _GLIBCXX_MOF_INV_QUALS>();
+ }
+ else if constexpr (is_lvalue_reference_v<_Fn>)
+ {
+ _M_copy(__polyfunc::__base_of(__f));
+ _M_invoke = __polyfunc::__invoker_of(__f);
+ }
+ else
+ {
+ _M_move(__polyfunc::__base_of(__f));
+ _M_invoke = std::__exchange(__polyfunc::__invoker_of(__f), nullptr);
+ }
+ }
+
+ /// Stores a target object initialized from the arguments.
+ template<typename _Tp, typename... _Args>
+ requires is_constructible_v<_Tp, _Args...>
+ && __is_callable_from<_Tp>
+ explicit
+ copyable_function(in_place_type_t<_Tp>, _Args&&... __args)
+ noexcept(_S_nothrow_init<_Tp, _Args...>())
+ : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>())
+ {
+ static_assert(is_same_v<decay_t<_Tp>, _Tp>);
+ static_assert(is_copy_constructible_v<_Tp>);
+ _M_init<_Tp>(std::forward<_Args>(__args)...);
+ }
+
+ /// Stores a target object initialized from the arguments.
+ template<typename _Tp, typename _Up, typename... _Args>
+ requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
+ && __is_callable_from<_Tp>
+ explicit
+ copyable_function(in_place_type_t<_Tp>, initializer_list<_Up> __il,
+ _Args&&... __args)
+ noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>())
+ : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>())
+ {
+ static_assert(is_same_v<decay_t<_Tp>, _Tp>);
+ static_assert(is_copy_constructible_v<_Tp>);
+ _M_init<_Tp>(__il, std::forward<_Args>(__args)...);
+ }
+
+ /// Stores a new target object, leaving `x` empty.
+ copyable_function&
+ operator=(copyable_function&& __x) noexcept
+ {
+ // Standard requires support of self assigment, by specifying it as
+ // copy and swap.
+ if (this != std::addressof(__x)) [[likely]]
+ {
+ _Base::operator=(static_cast<_Base&&>(__x));
+ _M_invoke = std::__exchange(__x._M_invoke, nullptr);
+ }
+ return *this;
+ }
+
+ /// Stores a copy of the source target object
+ copyable_function&
+ operator=(const copyable_function& __x)
+ {
+ copyable_function(__x).swap(*this);
+ return *this;
+ }
+
+ /// Destroys the target object (if any).
+ copyable_function&
+ operator=(nullptr_t) noexcept
+ {
+ _M_reset();
+ _M_invoke = nullptr;
+ return *this;
+ }
+
+ /// Stores a new target object, initialized from the argument.
+ template<typename _Fn>
+ requires is_constructible_v<copyable_function, _Fn>
+ copyable_function&
+ operator=(_Fn&& __f)
+ noexcept(is_nothrow_constructible_v<copyable_function, _Fn>)
+ {
+ copyable_function(std::forward<_Fn>(__f)).swap(*this);
+ return *this;
+ }
+
+ ~copyable_function() = default;
+
+ /// True if a target object is present, false otherwise.
+ explicit operator bool() const noexcept
+ { return _M_invoke != nullptr; }
+
+ /** Invoke the target object.
+ *
+ * The target object will be invoked using the supplied arguments,
+ * and as an lvalue or rvalue, and as const or non-const, as dictated
+ * by the template arguments of the `copyable_function` specialization.
+ *
+ * @pre Must not be empty.
+ */
+ _Res
+ operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV_REF noexcept(_Noex)
+ {
+ __glibcxx_assert(*this != nullptr);
+ return _M_invoke(this->_M_storage, std::forward<_ArgTypes>(__args)...);
+ }
+
+ /// Exchange the target objects (if any).
+ void
+ swap(copyable_function& __x) noexcept
+ {
+ _Base::swap(__x);
+ std::swap(_M_invoke, __x._M_invoke);
+ }
+
+ /// Exchange the target objects (if any).
+ friend void
+ swap(copyable_function& __x, copyable_function& __y) noexcept
+ { __x.swap(__y); }
+
+ /// Check for emptiness by comparing with `nullptr`.
+ friend bool
+ operator==(const copyable_function& __x, nullptr_t) noexcept
+ { return __x._M_invoke == nullptr; }
+
+ private:
+ typename _Invoker::__storage_func_t _M_invoke = nullptr;
+
+ template<typename _Func>
+ friend auto&
+ __polyfunc::__invoker_of(_Func&) noexcept;
+
+ template<typename _Func>
+ friend auto&
+ __polyfunc::__base_of(_Func&) noexcept;
+
+ template<typename _Dst, typename _Src>
+ friend consteval bool
+ __polyfunc::__is_invoker_convertible() noexcept;
+ };
+
+#undef _GLIBCXX_MOF_CV_REF
+#undef _GLIBCXX_MOF_CV
+#undef _GLIBCXX_MOF_REF
+#undef _GLIBCXX_MOF_INV_QUALS
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
diff --git a/libstdc++-v3/include/bits/funcwrap.h b/libstdc++-v3/include/bits/funcwrap.h
new file mode 100644
index 0000000..4e05353
--- /dev/null
+++ b/libstdc++-v3/include/bits/funcwrap.h
@@ -0,0 +1,507 @@
+// Implementation of std::move_only_function and std::copyable_function -*- 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/funcwrap.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{functional}
+ */
+
+#ifndef _GLIBCXX_FUNCWRAP_H
+#define _GLIBCXX_FUNCWRAP_H 1
+
+#ifdef _GLIBCXX_SYSHDR
+#pragma GCC system_header
+#endif
+
+#include <bits/version.h>
+
+#if defined(__glibcxx_move_only_function) || defined(__glibcxx_copyable_function)
+
+#include <bits/invoke.h>
+#include <bits/utility.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /// @cond undocumented
+ template<typename _Tp>
+ inline constexpr bool __is_polymorphic_function_v = false;
+
+ namespace __polyfunc
+ {
+ union _Ptrs
+ {
+ void* _M_obj;
+ void (*_M_func)();
+ };
+
+ struct _Storage
+ {
+ void* _M_addr() noexcept { return &_M_bytes[0]; }
+ void const* _M_addr() const noexcept { return &_M_bytes[0]; }
+
+ template<typename _Tp>
+ static consteval bool
+ _S_stored_locally() noexcept
+ {
+ return sizeof(_Tp) <= sizeof(_Storage)
+ && alignof(_Tp) <= alignof(_Storage)
+ && is_nothrow_move_constructible_v<_Tp>;
+ }
+
+ template<typename _Tp, typename... _Args>
+ static consteval bool
+ _S_nothrow_init() noexcept
+ {
+ if constexpr (_S_stored_locally<_Tp>())
+ return is_nothrow_constructible_v<_Tp, _Args...>;
+ return false;
+ }
+
+ template<typename _Tp, typename... _Args>
+ void
+ _M_init(_Args&&... __args) noexcept(_S_nothrow_init<_Tp, _Args...>())
+ {
+ if constexpr (is_function_v<remove_pointer_t<_Tp>>)
+ {
+ static_assert( sizeof...(__args) <= 1 );
+ // __args can have up to one element, returns nullptr if empty.
+ _Tp __func = (nullptr, ..., __args);
+ _M_ptrs._M_func = reinterpret_cast<void(*)()>(__func);
+ }
+ else if constexpr (!_S_stored_locally<_Tp>())
+ _M_ptrs._M_obj = new _Tp(std::forward<_Args>(__args)...);
+ else
+ ::new (_M_addr()) _Tp(std::forward<_Args>(__args)...);
+ }
+
+ template<typename _Tp>
+ [[__gnu__::__always_inline__]]
+ _Tp*
+ _M_ptr() const noexcept
+ {
+ if constexpr (!_S_stored_locally<remove_const_t<_Tp>>())
+ return static_cast<_Tp*>(_M_ptrs._M_obj);
+ else if constexpr (is_const_v<_Tp>)
+ return static_cast<_Tp*>(_M_addr());
+ else
+ // _Manager and _Invoker pass _Storage by const&, even for mutable sources.
+ return static_cast<_Tp*>(const_cast<void*>(_M_addr()));
+ }
+
+ template<typename _Ref>
+ [[__gnu__::__always_inline__]]
+ _Ref
+ _M_ref() const noexcept
+ {
+ using _Tp = remove_reference_t<_Ref>;
+ if constexpr (is_function_v<remove_pointer_t<_Tp>>)
+ return reinterpret_cast<_Tp>(_M_ptrs._M_func);
+ else
+ return static_cast<_Ref>(*_M_ptr<_Tp>());
+ }
+
+ // We want to have enough space to store a simple delegate type.
+ struct _Delegate { void (_Storage::*__pfm)(); _Storage* __obj; };
+ union {
+ _Ptrs _M_ptrs;
+ alignas(_Delegate) alignas(void(*)())
+ unsigned char _M_bytes[sizeof(_Delegate)];
+ };
+ };
+
+ template<bool _Noex, typename _Ret, typename... _Args>
+ struct _Base_invoker
+ {
+ using _Signature = _Ret(*)(_Args...) noexcept(_Noex);
+
+ using __storage_func_t = _Ret(*)(const _Storage&, _Args...) noexcept(_Noex);
+ template<typename _Tp>
+ static consteval __storage_func_t
+ _S_storage()
+ { return &_S_call_storage<_Adjust_target<_Tp>>; }
+
+ private:
+ template<typename _Tp, typename _Td = remove_cvref_t<_Tp>>
+ using _Adjust_target =
+ __conditional_t<is_pointer_v<_Td> || is_member_pointer_v<_Td>, _Td, _Tp>;
+
+ template<typename _Tp>
+ static _Ret
+ _S_call_storage(const _Storage& __ref, _Args... __args) noexcept(_Noex)
+ {
+ return std::__invoke_r<_Ret>(__ref._M_ref<_Tp>(),
+ std::forward<_Args>(__args)...);
+ }
+ };
+
+ template<typename _Tp>
+ using __param_t = __conditional_t<is_scalar_v<_Tp>, _Tp, _Tp&&>;
+
+ template<bool _Noex, typename _Ret, typename... _Args>
+ using _Invoker = _Base_invoker<_Noex, remove_cv_t<_Ret>, __param_t<_Args>...>;
+
+ template<typename _Func>
+ auto&
+ __invoker_of(_Func& __f) noexcept
+ { return __f._M_invoke; }
+
+ template<typename _Func>
+ auto&
+ __base_of(_Func& __f) noexcept
+ { return static_cast<__like_t<_Func&, typename _Func::_Base>>(__f); }
+
+ template<typename _Src, typename _Dst>
+ consteval bool
+ __is_invoker_convertible() noexcept
+ {
+ if constexpr (requires { typename _Src::_Signature; })
+ return is_convertible_v<typename _Src::_Signature,
+ typename _Dst::_Signature>;
+ else
+ return false;
+ }
+
+ struct _Manager
+ {
+ enum class _Op
+ {
+ // saves address of entity in *__src to __target._M_ptrs,
+ _Address,
+ // moves entity stored in *__src to __target, __src becomes empty
+ _Move,
+ // copies entity stored in *__src to __target, supported only if
+ // _ProvideCopy is specified.
+ _Copy,
+ // destroys entity stored in __target, __src is ignoring
+ _Destroy,
+ };
+
+ // A function that performs operation __op on the __target and possibly __src.
+ using _Func = void (*)(_Op __op, _Storage& __target, const _Storage* __src);
+
+ // The no-op manager function for objects with no target.
+ static void _S_empty(_Op, _Storage&, const _Storage*) noexcept { }
+
+ template<bool _ProvideCopy, typename _Tp>
+ consteval static auto
+ _S_select()
+ {
+ if constexpr (is_function_v<remove_pointer_t<_Tp>>)
+ return &_S_func;
+ else if constexpr (!_Storage::_S_stored_locally<_Tp>())
+ return &_S_ptr<_ProvideCopy, _Tp>;
+ else if constexpr (is_trivially_copyable_v<_Tp>)
+ return &_S_trivial;
+ else
+ return &_S_local<_ProvideCopy, _Tp>;
+ }
+
+ private:
+ static void
+ _S_func(_Op __op, _Storage& __target, const _Storage* __src) noexcept
+ {
+ switch (__op)
+ {
+ case _Op::_Address:
+ case _Op::_Move:
+ case _Op::_Copy:
+ __target._M_ptrs._M_func = __src->_M_ptrs._M_func;
+ return;
+ case _Op::_Destroy:
+ return;
+ }
+ }
+
+ static void
+ _S_trivial(_Op __op, _Storage& __target, const _Storage* __src) noexcept
+ {
+ switch (__op)
+ {
+ case _Op::_Address:
+ __target._M_ptrs._M_obj = const_cast<void*>(__src->_M_addr());
+ return;
+ case _Op::_Move:
+ case _Op::_Copy:
+ // N.B. Creating _Storage starts lifetime of _M_bytes char array,
+ // that implicitly creates, amongst other, all possible trivially
+ // copyable objects, so we copy any object present in __src._M_bytes.
+ ::new (&__target) _Storage(*__src);
+ return;
+ case _Op::_Destroy:
+ return;
+ }
+ }
+
+ template<bool _Provide_copy, typename _Tp>
+ static void
+ _S_local(_Op __op, _Storage& __target, const _Storage* __src)
+ noexcept(!_Provide_copy)
+ {
+ switch (__op)
+ {
+ case _Op::_Address:
+ __target._M_ptrs._M_obj = __src->_M_ptr<_Tp>();
+ return;
+ case _Op::_Move:
+ {
+ _Tp* __obj = __src->_M_ptr<_Tp>();
+ ::new(__target._M_addr()) _Tp(std::move(*__obj));
+ __obj->~_Tp();
+ }
+ return;
+ case _Op::_Destroy:
+ __target._M_ptr<_Tp>()->~_Tp();
+ return;
+ case _Op::_Copy:
+ if constexpr (_Provide_copy)
+ ::new (__target._M_addr()) _Tp(__src->_M_ref<const _Tp&>());
+ else
+ __builtin_unreachable();
+ return;
+ }
+ }
+
+ template<bool _Provide_copy, typename _Tp>
+ static void
+ _S_ptr(_Op __op, _Storage& __target, const _Storage* __src)
+ noexcept(!_Provide_copy)
+ {
+ switch (__op)
+ {
+ case _Op::_Address:
+ case _Op::_Move:
+ __target._M_ptrs._M_obj = __src->_M_ptrs._M_obj;
+ return;
+ case _Op::_Destroy:
+ delete __target._M_ptr<_Tp>();
+ return;
+ case _Op::_Copy:
+ if constexpr (_Provide_copy)
+ __target._M_ptrs._M_obj = new _Tp(__src->_M_ref<const _Tp&>());
+ else
+ __builtin_unreachable();
+ return;
+ }
+ }
+ };
+
+ class _Mo_base
+ {
+ protected:
+ _Mo_base() noexcept
+ : _M_manage(_Manager::_S_empty)
+ { }
+
+ _Mo_base(_Mo_base&& __x) noexcept
+ { _M_move(__x); }
+
+ template<typename _Tp, typename... _Args>
+ static consteval bool
+ _S_nothrow_init() noexcept
+ { return _Storage::_S_nothrow_init<_Tp, _Args...>(); }
+
+ template<typename _Tp, typename... _Args>
+ void
+ _M_init(_Args&&... __args)
+ noexcept(_S_nothrow_init<_Tp, _Args...>())
+ {
+ _M_storage._M_init<_Tp>(std::forward<_Args>(__args)...);
+ _M_manage = _Manager::_S_select<false, _Tp>();
+ }
+
+ void
+ _M_move(_Mo_base& __x) noexcept
+ {
+ using _Op = _Manager::_Op;
+ _M_manage = std::__exchange(__x._M_manage, _Manager::_S_empty);
+ _M_manage(_Op::_Move, _M_storage, &__x._M_storage);
+ }
+
+ _Mo_base&
+ operator=(_Mo_base&& __x) noexcept
+ {
+ _M_destroy();
+ _M_move(__x);
+ return *this;
+ }
+
+ void
+ _M_reset() noexcept
+ {
+ _M_destroy();
+ _M_manage = _Manager::_S_empty;
+ }
+
+ ~_Mo_base()
+ { _M_destroy(); }
+
+ void
+ swap(_Mo_base& __x) noexcept
+ {
+ using _Op = _Manager::_Op;
+ // Order of operations here is more efficient if __x is empty.
+ _Storage __s;
+ __x._M_manage(_Op::_Move, __s, &__x._M_storage);
+ _M_manage(_Op::_Move, __x._M_storage, &_M_storage);
+ __x._M_manage(_Op::_Move, _M_storage, &__s);
+ std::swap(_M_manage, __x._M_manage);
+ }
+
+ _Storage _M_storage;
+
+ private:
+ void _M_destroy() noexcept
+ { _M_manage(_Manager::_Op::_Destroy, _M_storage, nullptr); }
+
+ _Manager::_Func _M_manage;
+
+#ifdef __glibcxx_copyable_function // C++ >= 26 && HOSTED
+ friend class _Cpy_base;
+#endif // __glibcxx_copyable_function
+ };
+
+} // namespace __polyfunc
+ /// @endcond
+
+#ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED
+ template<typename... _Signature>
+ class move_only_function; // not defined
+
+ /// @cond undocumented
+ template<typename _Tp>
+ constexpr bool __is_polymorphic_function_v<move_only_function<_Tp>> = true;
+
+ namespace __detail::__variant
+ {
+ template<typename> struct _Never_valueless_alt; // see <variant>
+
+ // Provide the strong exception-safety guarantee when emplacing a
+ // move_only_function into a variant.
+ template<typename... _Signature>
+ struct _Never_valueless_alt<std::move_only_function<_Signature...>>
+ : true_type
+ { };
+ } // namespace __detail::__variant
+ /// @endcond
+#endif // __glibcxx_move_only_function
+
+#ifdef __glibcxx_copyable_function // C++ >= 26 && HOSTED
+ /// @cond undocumented
+ namespace __polyfunc
+ {
+ class _Cpy_base : public _Mo_base
+ {
+ protected:
+ _Cpy_base() = default;
+
+ template<typename _Tp, typename... _Args>
+ void
+ _M_init(_Args&&... __args)
+ noexcept(_S_nothrow_init<_Tp, _Args...>())
+ {
+ _M_storage._M_init<_Tp>(std::forward<_Args>(__args)...);
+ _M_manage = _Manager::_S_select<true, _Tp>();
+ }
+
+ void
+ _M_copy(_Cpy_base const& __x)
+ {
+ using _Op = _Manager::_Op;
+ __x._M_manage(_Op::_Copy, _M_storage, &__x._M_storage);
+ _M_manage = __x._M_manage;
+ }
+
+ _Cpy_base(_Cpy_base&&) = default;
+
+ _Cpy_base(_Cpy_base const& __x)
+ { _M_copy(__x); }
+
+ _Cpy_base&
+ operator=(_Cpy_base&&) = default;
+
+ _Cpy_base&
+ // Needs to use copy and swap for exception guarantees.
+ operator=(_Cpy_base const&) = delete;
+ };
+ } // namespace __polyfunc
+ /// @endcond
+
+ template<typename... _Signature>
+ class copyable_function; // not defined
+
+ template<typename _Tp>
+ constexpr bool __is_polymorphic_function_v<copyable_function<_Tp>> = true;
+
+ namespace __detail::__variant
+ {
+ template<typename> struct _Never_valueless_alt; // see <variant>
+
+ // Provide the strong exception-safety guarantee when emplacing a
+ // copyable_function into a variant.
+ template<typename... _Signature>
+ struct _Never_valueless_alt<std::copyable_function<_Signature...>>
+ : true_type
+ { };
+ } // namespace __detail::__variant
+#endif // __glibcxx_copyable_function
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_REF &
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_REF &&
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#define _GLIBCXX_MOF_REF &
+#include "mofunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#define _GLIBCXX_MOF_REF &&
+#include "mofunc_impl.h"
+#endif // __glibcxx_move_only_function
+
+#ifdef __glibcxx_copyable_function // C++ >= 26 && HOSTED
+#include "cpyfunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#include "cpyfunc_impl.h"
+#define _GLIBCXX_MOF_REF &
+#include "cpyfunc_impl.h"
+#define _GLIBCXX_MOF_REF &&
+#include "cpyfunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#define _GLIBCXX_MOF_REF &
+#include "cpyfunc_impl.h"
+#define _GLIBCXX_MOF_CV const
+#define _GLIBCXX_MOF_REF &&
+#include "cpyfunc_impl.h"
+#endif // __glibcxx_copyable_function
+
+#endif // __glibcxx_copyable_function || __glibcxx_copyable_function
+#endif // _GLIBCXX_FUNCWRAP_H
diff --git a/libstdc++-v3/include/bits/mofunc_impl.h b/libstdc++-v3/include/bits/mofunc_impl.h
index 318a55e..1ceb910 100644
--- a/libstdc++-v3/include/bits/mofunc_impl.h
+++ b/libstdc++-v3/include/bits/mofunc_impl.h
@@ -62,8 +62,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Res, typename... _ArgTypes, bool _Noex>
class move_only_function<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
_GLIBCXX_MOF_REF noexcept(_Noex)>
- : _Mofunc_base
+ : __polyfunc::_Mo_base
{
+ using _Base = __polyfunc::_Mo_base;
+ using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>;
+ using _Signature = _Invoker::_Signature;
+
template<typename _Tp>
using __callable
= __conditional_t<_Noex,
@@ -87,7 +91,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Moves the target object, leaving the source empty.
move_only_function(move_only_function&& __x) noexcept
- : _Mofunc_base(static_cast<_Mofunc_base&&>(__x)),
+ : _Base(static_cast<_Base&&>(__x)),
_M_invoke(std::__exchange(__x._M_invoke, nullptr))
{ }
@@ -97,15 +101,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& (!__is_in_place_type_v<_Vt>) && __is_callable_from<_Vt>
move_only_function(_Fn&& __f) noexcept(_S_nothrow_init<_Vt, _Fn>())
{
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4255. move_only_function constructor should recognize empty
+ // copyable_functions
if constexpr (is_function_v<remove_pointer_t<_Vt>>
|| is_member_pointer_v<_Vt>
- || __is_move_only_function_v<_Vt>)
+ || __is_polymorphic_function_v<_Vt>)
{
if (__f == nullptr)
return;
}
- _M_init<_Vt>(std::forward<_Fn>(__f));
- _M_invoke = &_S_invoke<_Vt>;
+
+ if constexpr (__is_polymorphic_function_v<_Vt>
+ && __polyfunc::__is_invoker_convertible<_Vt, move_only_function>())
+ {
+ // Handle cases where _Fn is const reference to copyable_function,
+ // by firstly creating temporary and moving from it.
+ _Vt __tmp(std::forward<_Fn>(__f));
+ _M_move(__polyfunc::__base_of(__tmp));
+ _M_invoke = std::__exchange(__polyfunc::__invoker_of(__tmp), nullptr);
+ }
+ else
+ {
+ _M_init<_Vt>(std::forward<_Fn>(__f));
+ _M_invoke = _Invoker::template _S_storage<_Vt _GLIBCXX_MOF_INV_QUALS>();
+ }
}
/// Stores a target object initialized from the arguments.
@@ -115,7 +135,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit
move_only_function(in_place_type_t<_Tp>, _Args&&... __args)
noexcept(_S_nothrow_init<_Tp, _Args...>())
- : _M_invoke(&_S_invoke<_Tp>)
+ : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>())
{
static_assert(is_same_v<decay_t<_Tp>, _Tp>);
_M_init<_Tp>(std::forward<_Args>(__args)...);
@@ -129,7 +149,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
move_only_function(in_place_type_t<_Tp>, initializer_list<_Up> __il,
_Args&&... __args)
noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>())
- : _M_invoke(&_S_invoke<_Tp>)
+ : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>())
{
static_assert(is_same_v<decay_t<_Tp>, _Tp>);
_M_init<_Tp>(__il, std::forward<_Args>(__args)...);
@@ -139,8 +159,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
move_only_function&
operator=(move_only_function&& __x) noexcept
{
- _Mofunc_base::operator=(static_cast<_Mofunc_base&&>(__x));
- _M_invoke = std::__exchange(__x._M_invoke, nullptr);
+ // Standard requires support of self assigment, by specifying it as
+ // copy and swap.
+ if (this != std::addressof(__x)) [[likely]]
+ {
+ _Base::operator=(static_cast<_Base&&>(__x));
+ _M_invoke = std::__exchange(__x._M_invoke, nullptr);
+ }
return *this;
}
@@ -148,7 +173,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
move_only_function&
operator=(nullptr_t) noexcept
{
- _Mofunc_base::operator=(nullptr);
+ _M_reset();
_M_invoke = nullptr;
return *this;
}
@@ -167,7 +192,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
~move_only_function() = default;
/// True if a target object is present, false otherwise.
- explicit operator bool() const noexcept { return _M_invoke != nullptr; }
+ explicit operator bool() const noexcept
+ { return _M_invoke != nullptr; }
/** Invoke the target object.
*
@@ -181,14 +207,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV_REF noexcept(_Noex)
{
__glibcxx_assert(*this != nullptr);
- return _M_invoke(this, std::forward<_ArgTypes>(__args)...);
+ return _M_invoke(this->_M_storage, std::forward<_ArgTypes>(__args)...);
}
/// Exchange the target objects (if any).
void
swap(move_only_function& __x) noexcept
{
- _Mofunc_base::swap(__x);
+ _Base::swap(__x);
std::swap(_M_invoke, __x._M_invoke);
}
@@ -203,25 +229,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __x._M_invoke == nullptr; }
private:
- template<typename _Tp>
- using __param_t = __conditional_t<is_scalar_v<_Tp>, _Tp, _Tp&&>;
+ typename _Invoker::__storage_func_t _M_invoke = nullptr;
- using _Invoker = _Res (*)(_Mofunc_base _GLIBCXX_MOF_CV*,
- __param_t<_ArgTypes>...) noexcept(_Noex);
+ template<typename _Func>
+ friend auto&
+ __polyfunc::__invoker_of(_Func&) noexcept;
- template<typename _Tp>
- static _Res
- _S_invoke(_Mofunc_base _GLIBCXX_MOF_CV* __self,
- __param_t<_ArgTypes>... __args) noexcept(_Noex)
- {
- using _TpCv = _Tp _GLIBCXX_MOF_CV;
- using _TpInv = _Tp _GLIBCXX_MOF_INV_QUALS;
- return std::__invoke_r<_Res>(
- std::forward<_TpInv>(*_S_access<_TpCv>(__self)),
- std::forward<__param_t<_ArgTypes>>(__args)...);
- }
+ template<typename _Func>
+ friend auto&
+ __polyfunc::__base_of(_Func&) noexcept;
- _Invoker _M_invoke = nullptr;
+ template<typename _Dst, typename _Src>
+ friend consteval bool
+ __polyfunc::__is_invoker_convertible() noexcept;
};
#undef _GLIBCXX_MOF_CV_REF
diff --git a/libstdc++-v3/include/bits/move_only_function.h b/libstdc++-v3/include/bits/move_only_function.h
deleted file mode 100644
index 42b33d0..0000000
--- a/libstdc++-v3/include/bits/move_only_function.h
+++ /dev/null
@@ -1,218 +0,0 @@
-// Implementation of std::move_only_function -*- 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/move_only_function.h
- * This is an internal header file, included by other library headers.
- * Do not attempt to use it directly. @headername{functional}
- */
-
-#ifndef _GLIBCXX_MOVE_ONLY_FUNCTION_H
-#define _GLIBCXX_MOVE_ONLY_FUNCTION_H 1
-
-#ifdef _GLIBCXX_SYSHDR
-#pragma GCC system_header
-#endif
-
-#include <bits/version.h>
-
-#ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED
-
-#include <bits/invoke.h>
-#include <bits/utility.h>
-
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
- template<typename... _Signature>
- class move_only_function; // not defined
-
- /// @cond undocumented
- class _Mofunc_base
- {
- protected:
- _Mofunc_base() noexcept
- : _M_manage(_S_empty)
- { }
-
- _Mofunc_base(_Mofunc_base&& __x) noexcept
- {
- _M_manage = std::__exchange(__x._M_manage, _S_empty);
- _M_manage(_M_storage, &__x._M_storage);
- }
-
- template<typename _Tp, typename... _Args>
- static constexpr bool
- _S_nothrow_init() noexcept
- {
- if constexpr (__stored_locally<_Tp>)
- return is_nothrow_constructible_v<_Tp, _Args...>;
- return false;
- }
-
- template<typename _Tp, typename... _Args>
- void
- _M_init(_Args&&... __args) noexcept(_S_nothrow_init<_Tp, _Args...>())
- {
- if constexpr (__stored_locally<_Tp>)
- ::new (_M_storage._M_addr()) _Tp(std::forward<_Args>(__args)...);
- else
- _M_storage._M_p = new _Tp(std::forward<_Args>(__args)...);
-
- _M_manage = &_S_manage<_Tp>;
- }
-
- _Mofunc_base&
- operator=(_Mofunc_base&& __x) noexcept
- {
- _M_manage(_M_storage, nullptr);
- _M_manage = std::__exchange(__x._M_manage, _S_empty);
- _M_manage(_M_storage, &__x._M_storage);
- return *this;
- }
-
- _Mofunc_base&
- operator=(nullptr_t) noexcept
- {
- _M_manage(_M_storage, nullptr);
- _M_manage = _S_empty;
- return *this;
- }
-
- ~_Mofunc_base() { _M_manage(_M_storage, nullptr); }
-
- void
- swap(_Mofunc_base& __x) noexcept
- {
- // Order of operations here is more efficient if __x is empty.
- _Storage __s;
- __x._M_manage(__s, &__x._M_storage);
- _M_manage(__x._M_storage, &_M_storage);
- __x._M_manage(_M_storage, &__s);
- std::swap(_M_manage, __x._M_manage);
- }
-
- template<typename _Tp, typename _Self>
- static _Tp*
- _S_access(_Self* __self) noexcept
- {
- if constexpr (__stored_locally<remove_const_t<_Tp>>)
- return static_cast<_Tp*>(__self->_M_storage._M_addr());
- else
- return static_cast<_Tp*>(__self->_M_storage._M_p);
- }
-
- private:
- struct _Storage
- {
- void* _M_addr() noexcept { return &_M_bytes[0]; }
- const void* _M_addr() const noexcept { return &_M_bytes[0]; }
-
- // We want to have enough space to store a simple delegate type.
- struct _Delegate { void (_Storage::*__pfm)(); _Storage* __obj; };
- union {
- void* _M_p;
- alignas(_Delegate) alignas(void(*)())
- unsigned char _M_bytes[sizeof(_Delegate)];
- };
- };
-
- template<typename _Tp>
- static constexpr bool __stored_locally
- = sizeof(_Tp) <= sizeof(_Storage) && alignof(_Tp) <= alignof(_Storage)
- && is_nothrow_move_constructible_v<_Tp>;
-
- // A function that either destroys the target object stored in __target,
- // or moves the target object from *__src to __target.
- using _Manager = void (*)(_Storage& __target, _Storage* __src) noexcept;
-
- // The no-op manager function for objects with no target.
- static void _S_empty(_Storage&, _Storage*) noexcept { }
-
- // The real manager function for a target object of type _Tp.
- template<typename _Tp>
- static void
- _S_manage(_Storage& __target, _Storage* __src) noexcept
- {
- if constexpr (__stored_locally<_Tp>)
- {
- if (__src)
- {
- _Tp* __rval = static_cast<_Tp*>(__src->_M_addr());
- ::new (__target._M_addr()) _Tp(std::move(*__rval));
- __rval->~_Tp();
- }
- else
- static_cast<_Tp*>(__target._M_addr())->~_Tp();
- }
- else
- {
- if (__src)
- __target._M_p = __src->_M_p;
- else
- delete static_cast<_Tp*>(__target._M_p);
- }
- }
-
- _Storage _M_storage;
- _Manager _M_manage;
- };
-
- template<typename _Tp>
- inline constexpr bool __is_move_only_function_v = false;
- template<typename _Tp>
- constexpr bool __is_move_only_function_v<move_only_function<_Tp>> = true;
- /// @endcond
-
- namespace __detail::__variant
- {
- template<typename> struct _Never_valueless_alt; // see <variant>
-
- // Provide the strong exception-safety guarantee when emplacing a
- // move_only_function into a variant.
- template<typename... _Signature>
- struct _Never_valueless_alt<std::move_only_function<_Signature...>>
- : true_type
- { };
- } // namespace __detail::__variant
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace std
-
-#include "mofunc_impl.h"
-#define _GLIBCXX_MOF_CV const
-#include "mofunc_impl.h"
-#define _GLIBCXX_MOF_REF &
-#include "mofunc_impl.h"
-#define _GLIBCXX_MOF_REF &&
-#include "mofunc_impl.h"
-#define _GLIBCXX_MOF_CV const
-#define _GLIBCXX_MOF_REF &
-#include "mofunc_impl.h"
-#define _GLIBCXX_MOF_CV const
-#define _GLIBCXX_MOF_REF &&
-#include "mofunc_impl.h"
-
-#endif // __glibcxx_move_only_function
-#endif // _GLIBCXX_MOVE_ONLY_FUNCTION_H
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 2d34a8d..6ca148f 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1748,6 +1748,15 @@ ftms = {
};
ftms = {
+ name = copyable_function;
+ values = {
+ v = 202306;
+ cxxmin = 26;
+ hosted = yes;
+ };
+};
+
+ftms = {
name = out_ptr;
values = {
v = 202311;
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 24831f7..48a090c 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -1948,6 +1948,16 @@
#endif /* !defined(__cpp_lib_move_only_function) && defined(__glibcxx_want_move_only_function) */
#undef __glibcxx_want_move_only_function
+#if !defined(__cpp_lib_copyable_function)
+# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED
+# define __glibcxx_copyable_function 202306L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_copyable_function)
+# define __cpp_lib_copyable_function 202306L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_copyable_function) && defined(__glibcxx_want_copyable_function) */
+#undef __glibcxx_want_copyable_function
+
#if !defined(__cpp_lib_out_ptr)
# if (__cplusplus >= 202100L)
# define __glibcxx_out_ptr 202311L
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index b3192cf..f0b0252 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -1863,20 +1863,24 @@ namespace __format
_Spec<_CharT> _M_spec{};
};
+#ifdef __BFLT16_DIG__
+ using __bflt16_t = decltype(0.0bf16);
+#endif
+
// Decide how 128-bit floating-point types should be formatted (or not).
- // When supported, the typedef __format::__float128_t is the type that
- // format arguments should be converted to for storage in basic_format_arg.
+ // When supported, the typedef __format::__flt128_t is the type that format
+ // arguments should be converted to before passing them to __formatter_fp.
// Define the macro _GLIBCXX_FORMAT_F128 to say they're supported.
- // _GLIBCXX_FORMAT_F128=1 means __float128, _Float128 etc. will be formatted
- // by converting them to long double (or __ieee128 for powerpc64le).
- // _GLIBCXX_FORMAT_F128=2 means basic_format_arg needs to enable explicit
- // support for _Float128, rather than formatting it as another type.
+ // The __float128, _Float128 will be formatted by converting them to:
+ // __ieee128 (same as __float128) when _GLIBCXX_FORMAT_F128=1,
+ // long double when _GLIBCXX_FORMAT_F128=2,
+ // _Float128 when _GLIBCXX_FORMAT_F128=3.
#undef _GLIBCXX_FORMAT_F128
#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
// Format 128-bit floating-point types using __ieee128.
- using __float128_t = __ieee128;
+ using __flt128_t = __ieee128;
# define _GLIBCXX_FORMAT_F128 1
#ifdef __LONG_DOUBLE_IEEE128__
@@ -1910,14 +1914,14 @@ namespace __format
#elif defined _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128
// Format 128-bit floating-point types using long double.
- using __float128_t = long double;
-# define _GLIBCXX_FORMAT_F128 1
+ using __flt128_t = long double;
+# define _GLIBCXX_FORMAT_F128 2
#elif __FLT128_DIG__ && defined(_GLIBCXX_HAVE_FLOAT128_MATH)
// Format 128-bit floating-point types using _Float128.
- using __float128_t = _Float128;
-# define _GLIBCXX_FORMAT_F128 2
+ using __flt128_t = _Float128;
+# define _GLIBCXX_FORMAT_F128 3
# if __cplusplus == 202002L
// These overloads exist in the library, but are not declared for C++20.
@@ -2947,8 +2951,8 @@ namespace __format
};
#endif
-#if defined(__FLT128_DIG__) && _GLIBCXX_FORMAT_F128 == 1
- // Reuse __formatter_fp<C>::format<__float128_t, Out> for _Float128.
+#if defined(__FLT128_DIG__) && _GLIBCXX_FORMAT_F128
+ // Use __formatter_fp<C>::format<__format::__flt128_t, Out> for _Float128.
template<__format::__char _CharT>
struct formatter<_Float128, _CharT>
{
@@ -2962,17 +2966,45 @@ namespace __format
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(_Float128 __u, basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f.format((__format::__float128_t)__u, __fc); }
+ { return _M_f.format((__format::__flt128_t)__u, __fc); }
+
+ private:
+ __format::__formatter_fp<_CharT> _M_f;
+ };
+#endif
+
+#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128 != 1
+ // Reuse __formatter_fp<C>::format<__format::__flt128_t, Out> for __float128.
+ // This formatter is not declared if _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT is true,
+ // as __float128 when present is same type as __ieee128, which may be same as
+ // long double.
+ template<__format::__char _CharT>
+ struct formatter<__float128, _CharT>
+ {
+ formatter() = default;
+
+ [[__gnu__::__always_inline__]]
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc)
+ { return _M_f.parse(__pc); }
+
+ template<typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(__float128 __u, basic_format_context<_Out, _CharT>& __fc) const
+ { return _M_f.format((__format::__flt128_t)__u, __fc); }
private:
__format::__formatter_fp<_CharT> _M_f;
+
+ static_assert( !is_same_v<__float128, long double>,
+ "This specialization should not be used for long double" );
};
#endif
#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
// Reuse __formatter_fp<C>::format<float, Out> for bfloat16_t.
template<__format::__char _CharT>
- struct formatter<__gnu_cxx::__bfloat16_t, _CharT>
+ struct formatter<__format::__bflt16_t, _CharT>
{
formatter() = default;
@@ -3835,16 +3867,14 @@ namespace __format
enum _Arg_t : unsigned char {
_Arg_none, _Arg_bool, _Arg_c, _Arg_i, _Arg_u, _Arg_ll, _Arg_ull,
_Arg_flt, _Arg_dbl, _Arg_ldbl, _Arg_str, _Arg_sv, _Arg_ptr, _Arg_handle,
- _Arg_i128, _Arg_u128,
- _Arg_bf16, _Arg_f16, _Arg_f32, _Arg_f64, // These are unused.
+ _Arg_i128, _Arg_u128, _Arg_float128,
+ _Arg_bf16, _Arg_f16, _Arg_f32, _Arg_f64,
+ _Arg_max_,
+
#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
- _Arg_next_value_,
- _Arg_f128 = _Arg_ldbl,
- _Arg_ibm128 = _Arg_next_value_,
-#else
- _Arg_f128,
+ _Arg_ibm128 = _Arg_ldbl,
+ _Arg_ieee128 = _Arg_float128,
#endif
- _Arg_max_
};
template<typename _Context>
@@ -3871,6 +3901,12 @@ namespace __format
double _M_dbl;
#ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT // No long double if it's ambiguous.
long double _M_ldbl;
+#else
+ __ibm128 _M_ibm128;
+ __ieee128 _M_ieee128;
+#endif
+#ifdef __SIZEOF_FLOAT128__
+ __float128 _M_float128;
#endif
const _CharT* _M_str;
basic_string_view<_CharT> _M_sv;
@@ -3880,11 +3916,17 @@ namespace __format
__int128 _M_i128;
unsigned __int128 _M_u128;
#endif
-#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
- __ieee128 _M_f128;
- __ibm128 _M_ibm128;
-#elif _GLIBCXX_FORMAT_F128 == 2
- __float128_t _M_f128;
+#ifdef __BFLT16_DIG__
+ __bflt16_t _M_bf16;
+#endif
+#ifdef __FLT16_DIG__
+ _Float16 _M_f16;
+#endif
+#ifdef __FLT32_DIG__
+ _Float32 _M_f32;
+#endif
+#ifdef __FLT64_DIG__
+ _Float64 _M_f64;
#endif
};
@@ -3922,10 +3964,14 @@ namespace __format
else if constexpr (is_same_v<_Tp, long double>)
return __u._M_ldbl;
#else
- else if constexpr (is_same_v<_Tp, __ieee128>)
- return __u._M_f128;
else if constexpr (is_same_v<_Tp, __ibm128>)
return __u._M_ibm128;
+ else if constexpr (is_same_v<_Tp, __ieee128>)
+ return __u._M_ieee128;
+#endif
+#ifdef __SIZEOF_FLOAT128__
+ else if constexpr (is_same_v<_Tp, __float128>)
+ return __u._M_float128;
#endif
else if constexpr (is_same_v<_Tp, const _CharT*>)
return __u._M_str;
@@ -3939,9 +3985,21 @@ namespace __format
else if constexpr (is_same_v<_Tp, unsigned __int128>)
return __u._M_u128;
#endif
-#if _GLIBCXX_FORMAT_F128 == 2
- else if constexpr (is_same_v<_Tp, __float128_t>)
- return __u._M_f128;
+#ifdef __BFLT16_DIG__
+ else if constexpr (is_same_v<_Tp, __bflt16_t>)
+ return __u._M_bf16;
+#endif
+#ifdef __FLT16_DIG__
+ else if constexpr (is_same_v<_Tp, _Float16>)
+ return __u._M_f16;
+#endif
+#ifdef __FLT32_DIG__
+ else if constexpr (is_same_v<_Tp, _Float32>)
+ return __u._M_f32;
+#endif
+#ifdef __FLT64_DIG__
+ else if constexpr (is_same_v<_Tp, _Float64>)
+ return __u._M_f64;
#endif
else if constexpr (derived_from<_Tp, _HandleBase>)
return static_cast<_Tp&>(__u._M_handle);
@@ -4120,36 +4178,25 @@ namespace __format
else if constexpr (is_same_v<_Td, __ieee128>)
return type_identity<__ieee128>();
#endif
-
-#if defined(__FLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
- else if constexpr (is_same_v<_Td, _Float16>)
- return type_identity<float>();
+#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128
+ else if constexpr (is_same_v<_Td, __float128>)
+ return type_identity<__float128>();
#endif
-
-#if defined(__BFLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
- else if constexpr (is_same_v<_Td, decltype(0.0bf16)>)
- return type_identity<float>();
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ else if constexpr (is_same_v<_Td, __format::__bflt16_t>)
+ return type_identity<__format::__bflt16_t>();
+#endif
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ else if constexpr (is_same_v<_Td, _Float16>)
+ return type_identity<_Float16>();
#endif
-
#if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
else if constexpr (is_same_v<_Td, _Float32>)
- return type_identity<float>();
+ return type_identity<_Float32>();
#endif
-
#if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
else if constexpr (is_same_v<_Td, _Float64>)
- return type_identity<double>();
-#endif
-
-#if _GLIBCXX_FORMAT_F128
-# if __FLT128_DIG__
- else if constexpr (is_same_v<_Td, _Float128>)
- return type_identity<__format::__float128_t>();
-# endif
-# if __SIZEOF_FLOAT128__
- else if constexpr (is_same_v<_Td, __float128>)
- return type_identity<__format::__float128_t>();
-# endif
+ return type_identity<_Float64>();
#endif
else if constexpr (__is_specialization_of<_Td, basic_string_view>
|| __is_specialization_of<_Td, basic_string>)
@@ -4205,7 +4252,27 @@ namespace __format
else if constexpr (is_same_v<_Tp, __ibm128>)
return _Arg_ibm128;
else if constexpr (is_same_v<_Tp, __ieee128>)
- return _Arg_f128;
+ return _Arg_ieee128;
+#endif
+#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128
+ else if constexpr (is_same_v<_Tp, __float128>)
+ return _Arg_float128;
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ else if constexpr (is_same_v<_Tp, __format::__bflt16_t>)
+ return _Arg_bf16;
+#endif
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ else if constexpr (is_same_v<_Tp, _Float16>)
+ return _Arg_f16;
+#endif
+#if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ else if constexpr (is_same_v<_Tp, _Float32>)
+ return _Arg_f32;
+#endif
+#if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+ else if constexpr (is_same_v<_Tp, _Float64>)
+ return _Arg_f64;
#endif
else if constexpr (is_same_v<_Tp, const _CharT*>)
return _Arg_str;
@@ -4219,11 +4286,6 @@ namespace __format
else if constexpr (is_same_v<_Tp, unsigned __int128>)
return _Arg_u128;
#endif
-
-#if _GLIBCXX_FORMAT_F128 == 2
- else if constexpr (is_same_v<_Tp, __format::__float128_t>)
- return _Arg_f128;
-#endif
else if constexpr (is_same_v<_Tp, handle>)
return _Arg_handle;
}
@@ -4296,13 +4358,33 @@ namespace __format
#ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
case _Arg_ldbl:
return std::forward<_Visitor>(__vis)(_M_val._M_ldbl);
+#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128
+ case _Arg_float128:
+ return std::forward<_Visitor>(__vis)(_M_val._M_float128);
+#endif
#else
- case _Arg_f128:
- return std::forward<_Visitor>(__vis)(_M_val._M_f128);
case _Arg_ibm128:
return std::forward<_Visitor>(__vis)(_M_val._M_ibm128);
+ case _Arg_ieee128:
+ return std::forward<_Visitor>(__vis)(_M_val._M_ieee128);
#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ case _Arg_bf16:
+ return std::forward<_Visitor>(__vis)(_M_val._M_bf16);
+#endif
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ case _Arg_f16:
+ return std::forward<_Visitor>(__vis)(_M_val._M_f16);
+#endif
+#if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ case _Arg_f32:
+ return std::forward<_Visitor>(__vis)(_M_val._M_f32);
#endif
+#if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+ case _Arg_f64:
+ return std::forward<_Visitor>(__vis)(_M_val._M_f64);
+#endif
+#endif // __glibcxx_to_chars
case _Arg_str:
return std::forward<_Visitor>(__vis)(_M_val._M_str);
case _Arg_sv:
@@ -4320,14 +4402,7 @@ namespace __format
case _Arg_u128:
return std::forward<_Visitor>(__vis)(_M_val._M_u128);
#endif
-
-#if _GLIBCXX_FORMAT_F128 == 2
- case _Arg_f128:
- return std::forward<_Visitor>(__vis)(_M_val._M_f128);
-#endif
-
default:
- // _Arg_f16 etc.
__builtin_unreachable();
}
}
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 1077e96..9a55b18 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -52,6 +52,20 @@
#if __cplusplus >= 201103L
+#define __glibcxx_want_boyer_moore_searcher
+#define __glibcxx_want_bind_front
+#define __glibcxx_want_bind_back
+#define __glibcxx_want_constexpr_functional
+#define __glibcxx_want_copyable_function
+#define __glibcxx_want_invoke
+#define __glibcxx_want_invoke_r
+#define __glibcxx_want_move_only_function
+#define __glibcxx_want_not_fn
+#define __glibcxx_want_ranges
+#define __glibcxx_want_reference_wrapper
+#define __glibcxx_want_transparent_operators
+#include <bits/version.h>
+
#include <tuple>
#include <type_traits>
#include <bits/functional_hash.h>
@@ -72,23 +86,10 @@
# include <bits/ranges_cmp.h> // std::identity, ranges::equal_to etc.
# include <compare>
#endif
-#if __cplusplus > 202002L && _GLIBCXX_HOSTED
-# include <bits/move_only_function.h>
+#if defined(__glibcxx_move_only_function) || defined(__glibcxx_copyable_function)
+# include <bits/funcwrap.h>
#endif
-#define __glibcxx_want_boyer_moore_searcher
-#define __glibcxx_want_bind_front
-#define __glibcxx_want_bind_back
-#define __glibcxx_want_constexpr_functional
-#define __glibcxx_want_invoke
-#define __glibcxx_want_invoke_r
-#define __glibcxx_want_move_only_function
-#define __glibcxx_want_not_fn
-#define __glibcxx_want_ranges
-#define __glibcxx_want_reference_wrapper
-#define __glibcxx_want_transparent_operators
-#include <bits/version.h>
-
#endif // C++11
namespace std _GLIBCXX_VISIBILITY(default)
diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index 1c15c75..8a85ccf 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -201,7 +201,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef __cpp_lib_to_underlying // C++ >= 23
/// Convert an object of enumeration type to its underlying type.
template<typename _Tp>
- [[nodiscard]]
+ [[nodiscard, __gnu__::__always_inline__]]
constexpr underlying_type_t<_Tp>
to_underlying(_Tp __value) noexcept
{ return static_cast<underlying_type_t<_Tp>>(__value); }