This patch implements C++26 copyable_function as specified in P2548R6.
It also implements LWG 4255 that adjust move_only_function so constructing
from empty copyable_function, produces empty functor. This falls from
existing checks, after specializing __is_polymorphic_function_v for
copyable_function specializations.

For compatible invoker signatures, the move_only_function may be constructed
from copyable_funciton without double indirection. To achieve that we derive
_Cpy_base from _Mo_base, and specialize __is_polymorphic_function_v for
copyable_function. Similary copyable_functions with compatible signatures
can be converted without double indirection.

As we starting to use _Op::_Copy operation from the _M_manage function,
invocations of that functions may now throw exceptions, so noexcept needs
to be removed from the signature of stored _M_manage pointers. This also
affects operations in _Mo_base, however we already wrap _M_manage invocations
in noexcept member functions (_M_move, _M_destroy, swap).

        PR libstdc++/119125

libstdc++-v3/ChangeLog:

        * doc/doxygen/stdheader.cc: Addded cpyfunc_impl.h header.
        * include/Makefile.am: Add bits cpyfunc_impl.h.
        * include/Makefile.in: Add bits cpyfunc_impl.h.
        * include/bits/cpyfunc_impl.h: New file.
        * include/bits/mofunc_impl.h: Mention LWG 4255.
        * include/bits/move_only_function.h: Update header description
        and change guard to __cplusplus > 202002L.
        (_Manager::_Func): Remove noexcept.
        (std::__is_polymorphic_function_v<move_only_function<_Tp>>)
        
(__variant::_Never_valueless_alt<std::move_only_function<_Signature...>>)
        (move_only_function) [__glibcxx_move_only_function]: Adjust guard.
        (std::__is_polymorphic_function_v<copyable_function<_Tp>>)
        (__variant::_Never_valueless_alt<std::copyable_function<_Signature...>>)
        (__polyfunc::_Cpy_base, std::copyable_function) 
[__glibcxx_copyable_function]:
        Define.
        * include/bits/version.def: Define copyable_function.
        * include/bits/version.h: Regenerate.
        * include/std/functional: Define __cpp_lib_copyable_function.
        * testsuite/20_util/copyable_function/call.cc: New test based on
        move_only_function tests.
        * testsuite/20_util/copyable_function/cons.cc: New test based on
        move_only_function tests.
        * testsuite/20_util/copyable_function/conv.cc: New test based on
        move_only_function tests.
        * testsuite/20_util/copyable_function/copy.cc: New test.
        * testsuite/20_util/copyable_function/move.cc: New test based on
        move_only_function tests.
---
 libstdc++-v3/doc/doxygen/stdheader.cc         |   1 +
 libstdc++-v3/include/Makefile.am              |   1 +
 libstdc++-v3/include/Makefile.in              |   1 +
 libstdc++-v3/include/bits/cpyfunc_impl.h      | 268 ++++++++++++++++++
 libstdc++-v3/include/bits/mofunc_impl.h       |   4 +
 .../include/bits/move_only_function.h         |  91 +++++-
 libstdc++-v3/include/bits/version.def         |  10 +
 libstdc++-v3/include/bits/version.h           |  10 +
 libstdc++-v3/include/std/functional           |   1 +
 .../20_util/copyable_function/call.cc         | 210 ++++++++++++++
 .../20_util/copyable_function/cons.cc         | 126 ++++++++
 .../20_util/copyable_function/conv.cc         | 253 +++++++++++++++++
 .../20_util/copyable_function/copy.cc         | 154 ++++++++++
 .../20_util/copyable_function/move.cc         | 120 ++++++++
 14 files changed, 1246 insertions(+), 4 deletions(-)
 create mode 100644 libstdc++-v3/include/bits/cpyfunc_impl.h
 create mode 100644 libstdc++-v3/testsuite/20_util/copyable_function/call.cc
 create mode 100644 libstdc++-v3/testsuite/20_util/copyable_function/cons.cc
 create mode 100644 libstdc++-v3/testsuite/20_util/copyable_function/conv.cc
 create mode 100644 libstdc++-v3/testsuite/20_util/copyable_function/copy.cc
 create mode 100644 libstdc++-v3/testsuite/20_util/copyable_function/move.cc

diff --git a/libstdc++-v3/doc/doxygen/stdheader.cc 
b/libstdc++-v3/doc/doxygen/stdheader.cc
index 3ee825feb66..8a201334410 100644
--- a/libstdc++-v3/doc/doxygen/stdheader.cc
+++ b/libstdc++-v3/doc/doxygen/stdheader.cc
@@ -54,6 +54,7 @@ void init_map()
     headers["function.h"]               = "functional";
     headers["functional_hash.h"]        = "functional";
     headers["mofunc_impl.h"]            = "functional";
+    headers["cpyfunc_impl.h"]           = "functional";
     headers["move_only_function.h"]     = "functional";
     headers["invoke.h"]                 = "functional";
     headers["ranges_cmp.h"]             = "functional";
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 1140fa0dffd..5cc13381b02 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 \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index c96e981acd6..6e5e97aa236 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 \
diff --git a/libstdc++-v3/include/bits/cpyfunc_impl.h 
b/libstdc++-v3/include/bits/cpyfunc_impl.h
new file mode 100644
index 00000000000..c2840032494
--- /dev/null
+++ b/libstdc++-v3/include/bits/cpyfunc_impl.h
@@ -0,0 +1,268 @@
+// 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 function wrapper.
+   *  @ingroup functors
+   *  @since C++23
+   *  @headerfile functional
+   *
+   *  The `std::copyable_function` class template is a call wrapper similar
+   *  to `std::function`, but does not require the stored target function
+   *  to be copyable.
+   *
+   *  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.mov.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 != addressof(__x)) [[likely]]
+         {
+           _Base::operator=(static_cast<_Base&&>(__x));
+           _M_invoke = std::__exchange(__x._M_invoke, nullptr);
+         }
+       return *this;
+      }
+
+      /// Stores a copy of 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/mofunc_impl.h 
b/libstdc++-v3/include/bits/mofunc_impl.h
index 839f19e0389..68264bd9547 100644
--- a/libstdc++-v3/include/bits/mofunc_impl.h
+++ b/libstdc++-v3/include/bits/mofunc_impl.h
@@ -101,6 +101,9 @@ _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_polymorphic_function_v<_Vt>)
@@ -108,6 +111,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
              if (__f == nullptr)
                return;
            }
+
          if constexpr (__is_polymorphic_function_v<_Vt>
                          && __polyfunc::__is_invoker_convertible<_Vt, 
move_only_function>())
            {
diff --git a/libstdc++-v3/include/bits/move_only_function.h 
b/libstdc++-v3/include/bits/move_only_function.h
index 58d6f2ee29e..9a2a384dfa5 100644
--- a/libstdc++-v3/include/bits/move_only_function.h
+++ b/libstdc++-v3/include/bits/move_only_function.h
@@ -1,4 +1,4 @@
-// Implementation of std::move_only_function -*- C++ -*-
+// Implementation of std::move_only_function and std::copyable_function -*- 
C++ -*-
 
 // Copyright The GNU Toolchain Authors.
 //
@@ -36,7 +36,7 @@
 
 #include <bits/version.h>
 
-#ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED
+#if __cplusplus > 202002L && _GLIBCXX_HOSTED
 
 #include <bits/invoke.h>
 #include <bits/utility.h>
@@ -143,7 +143,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
      };
 
     // A function that performs operation __op on the __target and possibly 
__src.
-    using _Func = void (*)(_Op __op, _Storage& __target, const _Storage* 
__src) noexcept;
+    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 { }
@@ -351,6 +351,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
      { _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
    };
 
    template<typename _Func>
@@ -376,6 +380,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 } // namespace __polyfunc
   /// @endcond
 
+#ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED
   template<typename... _Signature>
     class move_only_function; // not defined
 
@@ -395,10 +400,71 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { };
   }  // 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"
@@ -412,6 +478,23 @@ _GLIBCXX_END_NAMESPACE_VERSION
 #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 // __cplusplus > 202002L && _GLIBCXX_HOSTED
 #endif // _GLIBCXX_MOVE_ONLY_FUNCTION_H
diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index f4d3de88bb2..771e5b67cce 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1749,6 +1749,16 @@ ftms = {
   };
 };
 
+ftms = {
+  name = copyable_function;
+  values = {
+    v = 202306;
+    cxxmin = 26;
+    hosted = yes;
+  };
+};
+
+
 ftms = {
   name = out_ptr;
   values = {
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index d5d75cef2de..37c3ba01ab2 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/functional 
b/libstdc++-v3/include/std/functional
index 1077e9678d1..46179998eeb 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -80,6 +80,7 @@
 #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
diff --git a/libstdc++-v3/testsuite/20_util/copyable_function/call.cc 
b/libstdc++-v3/testsuite/20_util/copyable_function/call.cc
new file mode 100644
index 00000000000..36b9ec6f6e3
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/copyable_function/call.cc
@@ -0,0 +1,210 @@
+// { dg-do run { target c++26 } }
+// { dg-require-effective-target hosted }
+
+#include <functional>
+#include <utility>
+#include <testsuite_hooks.h>
+
+using std::copyable_function;
+
+using std::is_same_v;
+using std::is_invocable_v;
+using std::is_nothrow_invocable_v;
+using std::invoke_result_t;
+
+// Check return types
+static_assert( is_same_v<void, invoke_result_t<copyable_function<void()>>> );
+static_assert( is_same_v<int, invoke_result_t<copyable_function<int()>>> );
+static_assert( is_same_v<int&, invoke_result_t<copyable_function<int&()>>> );
+
+// With const qualifier
+static_assert( ! is_invocable_v< copyable_function<void()> const > );
+static_assert( ! is_invocable_v< copyable_function<void()> const &> );
+static_assert( is_invocable_v< copyable_function<void() const> > );
+static_assert( is_invocable_v< copyable_function<void() const> &> );
+static_assert( is_invocable_v< copyable_function<void() const> const > );
+static_assert( is_invocable_v< copyable_function<void() const> const &> );
+
+// With no ref-qualifier
+static_assert( is_invocable_v< copyable_function<void()> > );
+static_assert( is_invocable_v< copyable_function<void()> &> );
+static_assert( is_invocable_v< copyable_function<void() const> > );
+static_assert( is_invocable_v< copyable_function<void() const> &> );
+static_assert( is_invocable_v< copyable_function<void() const> const > );
+static_assert( is_invocable_v< copyable_function<void() const> const &> );
+
+// With & ref-qualifier
+static_assert( ! is_invocable_v< copyable_function<void()&> > );
+static_assert( is_invocable_v< copyable_function<void()&> &> );
+static_assert( is_invocable_v< copyable_function<void() const&> > );
+static_assert( is_invocable_v< copyable_function<void() const&> &> );
+static_assert( is_invocable_v< copyable_function<void() const&> const > );
+static_assert( is_invocable_v< copyable_function<void() const&> const &> );
+
+// With && ref-qualifier
+static_assert( is_invocable_v< copyable_function<void()&&> > );
+static_assert( ! is_invocable_v< copyable_function<void()&&> &> );
+static_assert( is_invocable_v< copyable_function<void() const&&> > );
+static_assert( ! is_invocable_v< copyable_function<void() const&&> &> );
+static_assert( is_invocable_v< copyable_function<void() const&&> const > );
+static_assert( ! is_invocable_v< copyable_function<void() const&&> const &> );
+
+// With noexcept-specifier
+static_assert( ! is_nothrow_invocable_v< copyable_function<void()> > );
+static_assert( ! is_nothrow_invocable_v< copyable_function<void() 
noexcept(false)> > );
+static_assert( is_nothrow_invocable_v< copyable_function<void() noexcept> > );
+static_assert( is_nothrow_invocable_v< copyable_function<void()& noexcept>& > 
);
+
+void
+test01()
+{
+  struct F
+  {
+    int operator()() { return 0; }
+    int operator()() const { return 1; }
+  };
+
+  copyable_function<int()> f0{F{}};
+  VERIFY( f0() == 0 );
+  VERIFY( std::move(f0)() == 0 );
+
+  copyable_function<int() const> f1{F{}};
+  VERIFY( f1() == 1 );
+  VERIFY( std::as_const(f1)() == 1 );
+  VERIFY( std::move(f1)() == 1 );
+  VERIFY( std::move(std::as_const(f1))() == 1 );
+
+  copyable_function<int()&> f2{F{}};
+  VERIFY( f2() == 0 );
+  // Not rvalue-callable: std::move(f2)()
+
+  copyable_function<int() const&> f3{F{}};
+  VERIFY( f3() == 1 );
+  VERIFY( std::as_const(f3)() == 1 );
+  VERIFY( std::move(f3)() == 1 );
+  VERIFY( std::move(std::as_const(f3))() == 1 );
+
+  copyable_function<int()&&> f4{F{}};
+  // Not lvalue-callable: f4()
+  VERIFY( std::move(f4)() == 0 );
+
+  copyable_function<int() const&&> f5{F{}};
+  // Not lvalue-callable: f5()
+  VERIFY( std::move(f5)() == 1 );
+  VERIFY( std::move(std::as_const(f5))() == 1 );
+}
+
+void
+test02()
+{
+  struct F
+  {
+    int operator()() & { return 0; }
+    int operator()() && { return 1; }
+  };
+
+  copyable_function<int()> f0{F{}};
+  VERIFY( f0() == 0 );
+  VERIFY( std::move(f0)() == 0 );
+
+  copyable_function<int()&&> f1{F{}};
+  // Not lvalue callable: f1()
+  VERIFY( std::move(f1)() == 1 );
+
+  copyable_function<int()&> f2{F{}};
+  VERIFY( f2() == 0 );
+  // Not rvalue-callable: std::move(f2)()
+}
+
+void
+test03()
+{
+  struct F
+  {
+    int operator()() const & { return 0; }
+    int operator()() && { return 1; }
+  };
+
+  copyable_function<int()> f0{F{}};
+  VERIFY( f0() == 0 );
+  VERIFY( std::move(f0)() == 0 );
+
+  copyable_function<int()&&> f1{F{}};
+  // Not lvalue callable: f1()
+  VERIFY( std::move(f1)() == 1 );
+
+  copyable_function<int() const> f2{F{}};
+  VERIFY( f2() == 0 );
+  VERIFY( std::as_const(f2)() == 0 );
+  VERIFY( std::move(f2)() == 0 );
+  VERIFY( std::move(std::as_const(f2))() == 0 );
+
+  copyable_function<int() const &&> f3{F{}};
+  // Not lvalue callable: f3()
+  VERIFY( std::move(f3)() == 0 );
+  VERIFY( std::move(std::as_const(f3))() == 0 );
+
+  copyable_function<int() const &> f4{F{}};
+  VERIFY( f4() == 0 );
+  VERIFY( std::as_const(f4)() == 0 );
+  // Not rvalue-callable: std::move(f4)()
+}
+
+void
+test04()
+{
+  struct F
+  {
+    int operator()() & { return 0; }
+    int operator()() && { return 1; }
+    int operator()() const & { return 2; }
+    int operator()() const && { return 3; }
+  };
+
+  copyable_function<int()> f0{F{}};
+  VERIFY( f0() == 0 );
+  VERIFY( std::move(f0)() == 0 );
+
+  copyable_function<int()&> f1{F{}};
+  VERIFY( f1() == 0 );
+  // Not rvalue-callable: std::move(f1)()
+
+  copyable_function<int()&&> f2{F{}};
+  // Not lvalue callable: f2()
+  VERIFY( std::move(f2)() == 1 );
+
+  copyable_function<int() const> f3{F{}};
+  VERIFY( f3() == 2 );
+  VERIFY( std::as_const(f3)() == 2 );
+  VERIFY( std::move(f3)() == 2 );
+  VERIFY( std::move(std::as_const(f3))() == 2 );
+
+  copyable_function<int() const &> f4{F{}};
+  VERIFY( f4() == 2 );
+  VERIFY( std::as_const(f4)() == 2 );
+  // Not rvalue-callable: std::move(f4)()
+
+  copyable_function<int() const &&> f5{F{}};
+  // Not lvalue callable: f5()
+  VERIFY( std::move(f5)() == 3 );
+  VERIFY( std::move(std::as_const(f5))() == 3 );
+}
+
+struct Incomplete;
+
+void
+test_params()
+{
+  std::copyable_function<void(Incomplete)> f1;
+  std::copyable_function<void(Incomplete&)> f2;
+  std::copyable_function<void(Incomplete&&)> f3;
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  test_params();
+}
diff --git a/libstdc++-v3/testsuite/20_util/copyable_function/cons.cc 
b/libstdc++-v3/testsuite/20_util/copyable_function/cons.cc
new file mode 100644
index 00000000000..8d422dcff8a
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/copyable_function/cons.cc
@@ -0,0 +1,126 @@
+// { dg-do compile { target c++26 } }
+// { dg-require-effective-target hosted }
+// { dg-add-options no_pch }
+
+#include <functional>
+
+#ifndef __cpp_lib_copyable_function
+# error "Feature-test macro for copyable_function missing in <functional>"
+#elif __cpp_lib_copyable_function != 202306L
+# error "Feature-test macro for copyable_function has wrong value in 
<functional>"
+#endif
+
+using std::copyable_function;
+
+using std::is_constructible_v;
+using std::is_copy_constructible_v;
+using std::is_nothrow_default_constructible_v;
+using std::is_nothrow_move_constructible_v;
+using std::is_nothrow_constructible_v;
+using std::nullptr_t;
+using std::in_place_type_t;
+
+static_assert( is_nothrow_default_constructible_v<copyable_function<void()>> );
+static_assert( is_nothrow_constructible_v<copyable_function<void()>, 
nullptr_t> );
+static_assert( is_nothrow_move_constructible_v<copyable_function<void()>> );
+static_assert( is_copy_constructible_v<copyable_function<void()>> );
+
+static_assert( is_constructible_v<copyable_function<void()>, void()> );
+static_assert( is_constructible_v<copyable_function<void()>, void(&)()> );
+static_assert( is_constructible_v<copyable_function<void()>, void(*)()> );
+static_assert( is_constructible_v<copyable_function<void()>, int()> );
+static_assert( is_constructible_v<copyable_function<void()>, int(&)()> );
+static_assert( is_constructible_v<copyable_function<void()>, int(*)()> );
+static_assert( ! is_constructible_v<copyable_function<void()>, void(int)> );
+static_assert( is_constructible_v<copyable_function<void(int)>, void(int)> );
+
+static_assert( is_constructible_v<copyable_function<void(int)>,
+                                 in_place_type_t<void(*)(int)>, void(int)> );
+
+static_assert( is_constructible_v<copyable_function<void()>,
+                                 void() noexcept> );
+static_assert( is_constructible_v<copyable_function<void() noexcept>,
+                                 void() noexcept> );
+static_assert( ! is_constructible_v<copyable_function<void() noexcept>,
+                                   void() > );
+
+struct Q
+{
+  void operator()() const &;
+  void operator()() &&;
+};
+
+static_assert( is_constructible_v<copyable_function<void()>, Q> );
+static_assert( is_constructible_v<copyable_function<void() const>, Q> );
+static_assert( is_constructible_v<copyable_function<void() &>, Q> );
+static_assert( is_constructible_v<copyable_function<void() const &>, Q> );
+static_assert( is_constructible_v<copyable_function<void() &&>, Q> );
+static_assert( is_constructible_v<copyable_function<void() const &&>, Q> );
+
+struct R
+{
+  void operator()() &;
+  void operator()() &&;
+};
+
+static_assert( is_constructible_v<copyable_function<void()>, R> );
+static_assert( is_constructible_v<copyable_function<void()&>, R> );
+static_assert( is_constructible_v<copyable_function<void()&&>, R> );
+static_assert( ! is_constructible_v<copyable_function<void() const>, R> );
+static_assert( ! is_constructible_v<copyable_function<void() const&>, R> );
+static_assert( ! is_constructible_v<copyable_function<void() const&&>, R> );
+
+// The following nothrow-constructible guarantees are a GCC extension,
+// not required by the standard.
+
+static_assert( is_nothrow_constructible_v<copyable_function<void()>, void()> );
+static_assert( is_nothrow_constructible_v<copyable_function<void(int)>,
+                                         in_place_type_t<void(*)(int)>,
+                                         void(int)> );
+
+// These types are all small and nothrow move constructible
+struct F { void operator()(); };
+struct G { void operator()() const; };
+static_assert( is_nothrow_constructible_v<copyable_function<void()>, F> );
+static_assert( is_nothrow_constructible_v<copyable_function<void()>, G> );
+static_assert( is_nothrow_constructible_v<copyable_function<void() const>, G> 
);
+
+struct H {
+  H(int);
+  H(int, int) noexcept;
+  void operator()() noexcept;
+};
+static_assert( is_nothrow_constructible_v<copyable_function<void()>, H> );
+static_assert( is_nothrow_constructible_v<copyable_function<void() noexcept>,
+                                         H> );
+static_assert( ! is_nothrow_constructible_v<copyable_function<void() noexcept>,
+                                           in_place_type_t<H>, int> );
+static_assert( is_nothrow_constructible_v<copyable_function<void() noexcept>,
+                                         in_place_type_t<H>, int, int> );
+
+struct I {
+  I(int, const char*);
+  I(std::initializer_list<char>);
+  int operator()() const noexcept;
+};
+
+static_assert( is_constructible_v<copyable_function<void()>,
+                                 std::in_place_type_t<I>,
+                                 int, const char*> );
+static_assert( is_constructible_v<copyable_function<void()>,
+                                 std::in_place_type_t<I>,
+                                 std::initializer_list<char>> );
+
+void
+test_instantiation()
+{
+  // Instantiate the constructor bodies
+  copyable_function<void()> f0;
+  copyable_function<void()> f1(nullptr);
+  copyable_function<void()> f2( I(1, "two") );
+  copyable_function<void()> f3(std::in_place_type<I>, 3, "four");
+  copyable_function<void()> f4(std::in_place_type<I>, // PR libstdc++/102825
+                               { 'P', 'R', '1', '0', '2', '8', '2', '5'});
+  auto f5 = std::move(f4);
+  f4 = std::move(f5);
+}
diff --git a/libstdc++-v3/testsuite/20_util/copyable_function/conv.cc 
b/libstdc++-v3/testsuite/20_util/copyable_function/conv.cc
new file mode 100644
index 00000000000..0f1b163a56a
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/copyable_function/conv.cc
@@ -0,0 +1,253 @@
+// { dg-do run { target c++26 } }
+// { dg-require-effective-target hosted }
+
+#include <functional>
+#include <testsuite_hooks.h>
+
+using std::copyable_function;
+
+static_assert( !std::is_constructible_v<std::copyable_function<void()>,
+                                       std::copyable_function<void()&>> );
+static_assert( !std::is_constructible_v<std::copyable_function<void()>,
+                                       std::copyable_function<void()&&>> );
+static_assert( !std::is_constructible_v<std::copyable_function<void()&>,
+                                       std::copyable_function<void()&&>> );
+static_assert( !std::is_constructible_v<std::copyable_function<void() const>,
+                                       std::copyable_function<void()>> );
+
+// Non-trivial args, guarantess that type is not passed by copy
+struct CountedArg
+{
+  CountedArg() = default;
+  CountedArg(const CountedArg& f) noexcept : counter(f.counter) { ++counter; }
+  CountedArg& operator=(CountedArg&&) = delete;
+
+  int counter = 0;
+};
+CountedArg const c;
+
+// When copyable_function or move_only_function is constructed from other 
copyable_function,
+// the compiler can avoid double indirection per C++26 [func.wrap.general] p2.
+
+void
+test01()
+{
+  auto f = [](CountedArg const& arg) noexcept { return arg.counter; };
+  std::copyable_function<int(CountedArg) const noexcept> c1(f);
+  using CF = std::copyable_function<int(CountedArg) const noexcept>;
+  VERIFY( c1(c) == 1 );
+
+  std::copyable_function<int(CountedArg) const> c2a(c1);
+  VERIFY( c2a(c) == 1 );
+
+  std::copyable_function<int(CountedArg) const> c2b(static_cast<CF>(c1));
+  VERIFY( c2b(c) == 1 );
+
+  std::move_only_function<int(CountedArg) const> m2a(c1);
+  VERIFY( m2a(c) == 1 );
+
+  std::move_only_function<int(CountedArg) const> m2b(static_cast<CF>(c1));
+  VERIFY( m2b(c) == 1 );
+
+  std::copyable_function<int(CountedArg)> c3a(c1);
+  VERIFY( c3a(c) == 1 );
+
+  std::copyable_function<int(CountedArg)> c3b(static_cast<CF>(c1));
+  VERIFY( c3b(c) == 1 );
+
+  std::move_only_function<int(CountedArg)> m3a(c1);
+  VERIFY( m3a(c) == 1 );
+
+  std::move_only_function<int(CountedArg)> m3b(static_cast<CF>(c1));
+  VERIFY( m3b(c) == 1 );
+
+  // Invokers internally uses Counted&& for non-trivial types,
+  // sinature remain compatible.
+  std::copyable_function<int(CountedArg&&)> c4a(c1);
+  VERIFY( c4a({}) == 0 );
+
+  std::copyable_function<int(CountedArg&&)> c4b(static_cast<CF>(c1));
+  VERIFY( c4b({}) == 0 );
+
+  std::move_only_function<int(CountedArg&&)> m4a(c1);
+  VERIFY( m4a({}) == 0 );
+
+  std::move_only_function<int(CountedArg&&)> m4b(static_cast<CF>(c1));
+  VERIFY( m4b({}) == 0 );
+
+  std::copyable_function<int(CountedArg&&)&> c5a(c1);
+  VERIFY( c5a({}) == 0 );
+
+  std::copyable_function<int(CountedArg&&)&&> c5b(static_cast<CF>(c1));
+  VERIFY( std::move(c5b)({}) == 0 );
+
+  std::move_only_function<int(CountedArg&&)&> m5a(c1);
+  VERIFY( m5a({}) == 0 );
+
+  std::move_only_function<int(CountedArg&&)&&> m5b(static_cast<CF>(c1));
+  VERIFY( std::move(m5b)({}) == 0 );
+
+  // Incompatible signatures
+  std::copyable_function<long(CountedArg) const noexcept> c6a(c1);
+  VERIFY( c6a(c) == 2 );
+
+  std::copyable_function<long(CountedArg) const noexcept> 
c6b(static_cast<CF>(c1));
+  VERIFY( c6b(c) == 2 );
+
+  std::move_only_function<long(CountedArg) const noexcept> m6a(c1);
+  VERIFY( m6a(c) == 2 );
+
+  std::move_only_function<long(CountedArg) const noexcept> 
m6b(static_cast<CF>(c1));
+  VERIFY( m6b(c) == 2 );
+}
+
+void
+test02()
+{
+  auto f = [](CountedArg const& arg) noexcept { return arg.counter; };
+  std::copyable_function<int(CountedArg) const noexcept> c1(f);
+  using CF = std::copyable_function<int(CountedArg) const noexcept>;
+  VERIFY( c1(c) == 1 );
+
+  std::copyable_function<int(CountedArg) const> c2;
+  c2 = c1;
+  VERIFY( c2(c) == 1 );
+  c2 = static_cast<CF>(c1);
+  VERIFY( c2(c) == 1 );
+
+  std::move_only_function<int(CountedArg) const> m2;
+  m2 = c1;
+  VERIFY( m2(c) == 1 );
+  m2 = static_cast<CF>(c1);
+  VERIFY( m2(c) == 1 );
+
+  // Incompatible signatures
+  std::copyable_function<long(CountedArg) const noexcept> c3;
+  c3 = c1;
+  VERIFY( c3(c) == 2 );
+  c3 = static_cast<CF>(c1);
+  VERIFY( c3(c) == 2 );
+
+  std::move_only_function<long(CountedArg) const noexcept> m3;
+  m3 = c1;
+  VERIFY( m3(c) == 2 );
+  m3 = static_cast<CF>(c1);
+  VERIFY( m3(c) == 2 );
+}
+
+void
+test03()
+{
+  std::copyable_function<int(long) const noexcept> c1;
+  VERIFY( c1 == nullptr );
+
+  std::copyable_function<int(long) const> c2(c1);
+  VERIFY( c2 == nullptr );
+  c2 = c1;
+  VERIFY( c2 == nullptr );
+  c2 = std::move(c1);
+  VERIFY( c2 == nullptr );
+
+  std::copyable_function<bool(int) const> c3(std::move(c1));
+  VERIFY( c3 == nullptr );
+  c3 = c1;
+  VERIFY( c3 == nullptr );
+  c3 = std::move(c1);
+  VERIFY( c3 == nullptr );
+
+  // Standard specifies this as move_only_function containing
+  // empty copyable_function, i.e. they are not equal nullptr.
+  // Invoking call operator remains UB, however we cannot 
+  // is UB, but it cannot be checked on user side.
+  std::move_only_function<int(long) const noexcept> m1(c1);
+  VERIFY( m1 == nullptr );
+  m1 = c1;
+  VERIFY( m1 == nullptr );
+  m1 = std::move(c1);
+  VERIFY( m1 == nullptr );
+
+  std::move_only_function<int(long) const> m2(c1);
+  VERIFY( m2 == nullptr );
+  m2 = c1;
+  VERIFY( m2 == nullptr );
+  m2 = std::move(c1);
+  VERIFY( m2 == nullptr );
+
+  std::move_only_function<bool(int) const> m3(std::move(c1));
+  VERIFY( m3 == nullptr );
+  m3 = c1;
+  VERIFY( m3 == nullptr );
+  m3 = std::move(c1);
+  VERIFY( m3 == nullptr );
+}
+
+void
+test04()
+{
+  struct F
+  {
+    int operator()(CountedArg const& arg) noexcept
+    { return arg.counter; }
+
+    int operator()(CountedArg const& arg) const noexcept
+    { return arg.counter + 1000; }
+  };
+
+  F f;
+  std::copyable_function<int(CountedArg) const> c1(f);
+  VERIFY( c1(c) == 1001 );
+
+  // Call const overload as std::copyable_function<int(CountedArg) const>
+  // inside td::copyable_function<int(CountedArg)> would do.
+  std::copyable_function<int(CountedArg)> c2(c1);
+  VERIFY( c2(c) == 1001 );
+  std::move_only_function<int(CountedArg)> m2(c1);
+  VERIFY( m2(c) == 1001 );
+
+  std::copyable_function<int(CountedArg)> m3(f);
+  VERIFY( m3(c) == 1 );
+}
+
+void
+test05()
+{
+  auto f = [](CountedArg const& arg) noexcept { return arg.counter; };
+  std::copyable_function<int(CountedArg)> w1(f);
+  // copyable_function stores copyable_function due incompatibile signatures
+  std::copyable_function<int(CountedArg const&)> w2(std::move(w1));
+  // copy is made when passing to int(CountedArg)
+  VERIFY( w2(c) == 1 );
+  // wrapped 3 times
+  w1 = std::move(w2);
+  VERIFY( w1(c) == 2 );
+  // wrapped 4 times
+  w2 = std::move(w1);
+  VERIFY( w2(c) == 2 );
+  // wrapped 5 times
+  w1 = std::move(w2);
+  VERIFY( w1(c) == 3 );
+}
+
+void
+test06()
+{
+  // No special interoperability with std::function
+  auto f = [](CountedArg const& arg) noexcept { return arg.counter; };
+  std::function<int(CountedArg)> f1(f);
+  std::copyable_function<int(CountedArg) const> c1(std::move(f1));
+  VERIFY( c1(c) == 2 );
+
+  std::copyable_function<int(CountedArg) const> c2(f);
+  std::function<int(CountedArg)> f2(c2);
+  VERIFY( f2(c) == 2 );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  test05();
+  test06();
+}
diff --git a/libstdc++-v3/testsuite/20_util/copyable_function/copy.cc 
b/libstdc++-v3/testsuite/20_util/copyable_function/copy.cc
new file mode 100644
index 00000000000..6445a272b79
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/copyable_function/copy.cc
@@ -0,0 +1,154 @@
+// { dg-do run { target c++26 } }
+// { dg-require-effective-target hosted }
+
+#include <functional>
+#include <testsuite_hooks.h>
+
+using std::copyable_function;
+
+void
+test01()
+{
+  // Small type with non-throwing move constructor. Not allocated on the heap.
+  struct F
+  {
+    F() = default;
+    F(const F& f) : counters(f.counters) { ++counters.copy; }
+    F(F&& f) noexcept : counters(f.counters) { ++counters.move; }
+
+    F& operator=(F&&) = delete;
+
+    struct Counters
+    {
+      int copy = 0;
+      int move = 0;
+    } counters;
+
+    const Counters& operator()() const { return counters; }
+  };
+
+  F f;
+  std::copyable_function<const F::Counters&() const> m1(f);
+  VERIFY( m1().copy == 1 );
+  VERIFY( m1().move == 0 );
+
+  // This will copy construct a new target object
+  auto m2 = m1;
+  VERIFY( m1 != nullptr && m2 != nullptr );
+  VERIFY( m2().copy == 2 );
+  VERIFY( m2().move == 0 );
+
+  m1 = m2;
+  VERIFY( m1 != nullptr && m2 != nullptr );
+  VERIFY( m1().copy == 3 );
+  VERIFY( m1().move == 1 ); // Copies object first and then swaps
+
+  m1 = m1;
+  VERIFY( m1 != nullptr && m2 != nullptr );
+  VERIFY( m1().copy == 4 );
+  VERIFY( m1().move == 2 ); // Copies object first and then swaps
+
+  m2 = f;
+  VERIFY( m2().copy == 1 );
+  VERIFY( m2().move == 1 ); // Copy construct target object, then swap into m2.
+}
+
+void
+test02()
+{
+  // Move constructor is potentially throwing. Allocated on the heap.
+  struct F
+  {
+    F() = default;
+    F(const F& f) noexcept : counters(f.counters) { ++counters.copy; }
+    F(F&& f) noexcept(false) : counters(f.counters) { ++counters.move; }
+
+    F& operator=(F&&) = delete;
+
+    struct Counters
+    {
+      int copy = 0;
+      int move = 0;
+    } counters;
+
+    Counters operator()() const noexcept { return counters; }
+  };
+
+  F f;
+  std::copyable_function<F::Counters() const> m1(f);
+  VERIFY( m1().copy == 1 );
+  VERIFY( m1().move == 0 );
+
+  // The target object is on the heap, but we need to allocate new one
+  auto m2 = m1;
+  VERIFY( m1 != nullptr && m2 != nullptr );
+  VERIFY( m2().copy == 2 );
+  VERIFY( m2().move == 0 );
+
+  m1 = m2;
+  VERIFY( m1 != nullptr && m2 != nullptr );
+  VERIFY( m1().copy == 3 );
+  VERIFY( m1().move == 0 );
+
+  m1 = m1;
+  VERIFY( m1 != nullptr && m2 != nullptr );
+  VERIFY( m1().copy == 4 );
+  VERIFY( m1().move == 0 );
+
+  m2 = f;
+  VERIFY( m2().copy == 1 );
+  VERIFY( m2().move == 0 );
+}
+
+void
+test03()
+{
+  // Small type with non-throwing, but not non-trivial move constructor.
+  struct F
+  {
+    F(int i) noexcept : id(i) {}
+    F(const F& f) : id(f.id)
+    { if (id == 3) throw id; }
+    F(F&& f) noexcept : id(f.id) {  }
+
+    int operator()() const
+    { return id; }
+
+    int id;
+  };
+
+  std::copyable_function<int() const> m1(std::in_place_type<F>, 1);
+  const std::copyable_function<int() const> m2(std::in_place_type<F>, 2);
+  const std::copyable_function<int() const> m3(std::in_place_type<F>, 3);
+
+  try
+  {
+    auto mc = m3;
+    VERIFY( false );
+  }
+  catch(int i)
+  {
+    VERIFY( i == 3 );
+  }
+
+  m1 = m2;
+  VERIFY( m1() == 2 );
+
+  try
+  {
+    m1 = m3;
+    VERIFY( false );
+  }
+  catch (int i)
+  {
+    VERIFY( i == 3 );
+  }
+  VERIFY( m1() == 2 );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+}
diff --git a/libstdc++-v3/testsuite/20_util/copyable_function/move.cc 
b/libstdc++-v3/testsuite/20_util/copyable_function/move.cc
new file mode 100644
index 00000000000..ec9d0d1af92
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/copyable_function/move.cc
@@ -0,0 +1,120 @@
+// { dg-do run { target c++26 } }
+// { dg-require-effective-target hosted }
+
+#include <functional>
+#include <testsuite_hooks.h>
+
+using std::copyable_function;
+
+void
+test01()
+{
+  // Small type with non-throwing move constructor. Not allocated on the heap.
+  struct F
+  {
+    F() = default;
+    F(const F& f) : counters(f.counters) { ++counters.copy; }
+    F(F&& f) noexcept : counters(f.counters) { ++counters.move; }
+
+    F& operator=(F&&) = delete;
+
+    struct Counters
+    {
+      int copy = 0;
+      int move = 0;
+    } counters;
+
+    const Counters& operator()() const { return counters; }
+  };
+
+  F f;
+  std::copyable_function<const F::Counters&() const> m1(f);
+  VERIFY( m1().copy == 1 );
+  VERIFY( m1().move == 0 );
+
+  // Standard specifies move assigment as copy and swap
+  m1 = std::move(m1);
+  VERIFY( m1 != nullptr );
+  VERIFY( m1().copy == 1 );
+  VERIFY( m1().move == 0 );
+
+  // This will move construct a new target object and destroy the old one:
+  auto m2 = std::move(m1);
+  VERIFY( m1 == nullptr && m2 != nullptr );
+  VERIFY( m2().copy == 1 );
+  VERIFY( m2().move == 1 );
+
+  m1 = std::move(m2);
+  VERIFY( m1 != nullptr && m2 == nullptr );
+  VERIFY( m1().copy == 1 );
+  VERIFY( m1().move == 2 );
+
+  m2 = std::move(f);
+  VERIFY( m2().copy == 0 );
+  VERIFY( m2().move == 2 ); // Move construct target object, then swap into m2.
+  const int moves = m1().move + m2().move;
+  // This will do three moves:
+  swap(m1, m2);
+  VERIFY( m1().copy == 0 );
+  VERIFY( m2().copy == 1 );
+  VERIFY( (m1().move + m2().move) == (moves + 3) );
+}
+
+void
+test02()
+{
+  // Move constructor is potentially throwing. Allocated on the heap.
+  struct F
+  {
+    F() = default;
+    F(const F& f) noexcept : counters(f.counters) { ++counters.copy; }
+    F(F&& f) noexcept(false) : counters(f.counters) { ++counters.move; }
+
+    F& operator=(F&&) = delete;
+
+    struct Counters
+    {
+      int copy = 0;
+      int move = 0;
+    } counters;
+
+    Counters operator()() const noexcept { return counters; }
+  };
+
+  F f;
+  std::copyable_function<F::Counters() const> m1(f);
+  VERIFY( m1().copy == 1 );
+  VERIFY( m1().move == 0 );
+
+  m1 = std::move(m1);
+  VERIFY( m1 != nullptr );
+  VERIFY( m1().copy == 1 );
+  VERIFY( m1().move == 0 );
+
+  // The target object is on the heap so this just moves a pointer:
+  auto m2 = std::move(m1);
+  VERIFY( m1 == nullptr && m2 != nullptr );
+  VERIFY( m2().copy == 1 );
+  VERIFY( m2().move == 0 );
+
+  m1 = std::move(m2);
+  VERIFY( m1 != nullptr && m2 == nullptr );
+  VERIFY( m1().copy == 1 );
+  VERIFY( m1().move == 0 );
+
+  m2 = std::move(f);
+  VERIFY( m2().copy == 0 );
+  VERIFY( m2().move == 1 );
+  const int moves = m1().move + m2().move;
+  // This just swaps the pointers, so no moves:
+  swap(m1, m2);
+  VERIFY( m1().copy == 0 );
+  VERIFY( m2().copy == 1 );
+  VERIFY( (m1().move + m2().move) == moves );
+}
+
+int main()
+{
+  test01();
+  test02();
+}
-- 
2.49.0

Reply via email to