https://gcc.gnu.org/g:52b44d966edc34611e01e505fee92f924a213df2

commit r16-8526-g52b44d966edc34611e01e505fee92f924a213df2
Author: Matthias Kretz <[email protected]>
Date:   Tue Nov 11 16:27:34 2025 +0100

    libstdc++: Remove non_type and replace it with constant_wrapper in 
function_ref
    
    This implements P3948R1: constant_wrapper is the only tool needed
    for passing constant expressions via function arguments.
    
    This changes function_ref from nontype_t to constant_wrapper and
    implements the ambiguity check (static_asert in function_ref
    from constant_wrapper constructor).
    
    In addition to P3948R1 this also includes the (forgotten) deduction
    guide changes suggested in the draft PR [1].
    
    [1] https://github.com/cplusplus/draft/pull/8878
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/funcref_impl.h (function_ref::function_ref):
            Change nontype_t parameter to constant_wrapper, and adjust
            accordingly. Add static_assert detecting ambigous semantics.
            (function_ref::operator=): Detect constant_wrapper rather than
            nontype_t.
            * include/bits/funcwrap.h (function_ref): Change nontype_t
            parameter to constant_wrapper in deduction guides.
            * include/bits/utility.h (std::nontype_t, std::nontype)
            (std::__is_nontype_v): Remove.
            (std::__is_constant_wrapper_v): Define.
            * src/c++23/std.cc.in (std::nontype_t, std::nontype):
            Remove exports.
            * testsuite/20_util/function_ref/cw_cons_neg.cc: New tests
            for ambiguity check.
            * testsuite/20_util/function_ref/assign.cc: Replace nontype_t
            with constant_wrapper and nontype with std::cw.
            * testsuite/20_util/function_ref/call.cc: Likewise.
            * testsuite/20_util/function_ref/cons.cc: Likewise.
            * testsuite/20_util/function_ref/cons_neg.cc: Likewise.
            * testsuite/20_util/function_ref/dangling.cc: Likewise.
            * testsuite/20_util/function_ref/deduction.cc: Likewise.
            * testsuite/20_util/function_ref/mutation.cc: Likewise.
    
    Co-authored-by: Tomasz Kamiński <[email protected]>
    Reviewed-by: Jonathan Wakely <[email protected]>
    Signed-off-by: Matthias Kretz <[email protected]>
    Signed-off-by: Tomasz Kamiński <[email protected]>

Diff:
---
 libstdc++-v3/include/bits/funcref_impl.h           | 36 ++++++----
 libstdc++-v3/include/bits/funcwrap.h               | 13 ++--
 libstdc++-v3/include/bits/utility.h                | 23 ++----
 libstdc++-v3/src/c++23/std.cc.in                   |  4 --
 .../testsuite/20_util/function_ref/assign.cc       | 27 ++++---
 .../testsuite/20_util/function_ref/call.cc         | 51 +++++++------
 .../testsuite/20_util/function_ref/cons.cc         | 83 +++++++++++-----------
 .../testsuite/20_util/function_ref/cons_neg.cc     | 17 +++--
 .../testsuite/20_util/function_ref/cw_cons_neg.cc  | 35 +++++++++
 .../testsuite/20_util/function_ref/dangling.cc     |  2 +-
 .../testsuite/20_util/function_ref/deduction.cc    | 48 ++++++-------
 .../testsuite/20_util/function_ref/mutation.cc     |  9 ++-
 12 files changed, 185 insertions(+), 163 deletions(-)

diff --git a/libstdc++-v3/include/bits/funcref_impl.h 
b/libstdc++-v3/include/bits/funcref_impl.h
index 3d55c8406b09..9fcab570803f 100644
--- a/libstdc++-v3/include/bits/funcref_impl.h
+++ b/libstdc++-v3/include/bits/funcref_impl.h
@@ -129,12 +129,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 4256. Incorrect constrains for function_ref constructors from nontype
       /// Target object is __fn. There is no bound object.
-      template<auto __fn>
-       requires __is_invocable_using<const decltype(__fn)&>
+      template<auto __cwfn, typename _Fn>
+       requires __is_invocable_using<const _Fn&>
        constexpr
-       function_ref(nontype_t<__fn>) noexcept
+       function_ref(constant_wrapper<__cwfn, _Fn>) noexcept
        {
-         using _Fn = remove_cv_t<decltype(__fn)>;
+         constexpr const _Fn& __fn = constant_wrapper<__cwfn, _Fn>::value;
+         if constexpr (sizeof...(_ArgTypes) > 0)
+           if constexpr ((... && _ConstExprParam<remove_cvref_t<_ArgTypes>>))
+             static_assert(!requires {
+               typename constant_wrapper<
+                 std::__invoke(__fn, remove_cvref_t<_ArgTypes>::value...)>;
+             }, "cw<fn>(args...) should be equivalent to fn(args...)");
+
          if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
            static_assert(__fn != nullptr);
 
@@ -144,13 +151,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       /// Target object is equivalent to std::bind_front<_fn>(std::ref(__ref)).
       /// Bound object is object referenced by second parameter.
-      template<auto __fn, typename _Up, typename _Td = remove_reference_t<_Up>>
+      template<auto __cwfn, typename _Fn, typename _Up,
+              typename _Td = remove_reference_t<_Up>>
        requires (!is_rvalue_reference_v<_Up&&>)
-         && __is_invocable_using<const decltype(__fn)&, _Td _GLIBCXX_MOF_CV&>
+                && __is_invocable_using<const _Fn&, _Td _GLIBCXX_MOF_CV&>
        constexpr
-       function_ref(nontype_t<__fn>, _Up&& __ref) noexcept
+       function_ref(constant_wrapper<__cwfn, _Fn>, _Up&& __ref) noexcept
        {
-         using _Fn = remove_cv_t<decltype(__fn)>;
+         constexpr const _Fn& __fn = constant_wrapper<__cwfn, _Fn>::value;
          if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
            static_assert(__fn != nullptr);
 
@@ -166,12 +174,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       /// Target object is equivalent to std::bind_front<_fn>(__ptr).
       /// Bound object is object pointed by second parameter (if any).
-      template<auto __fn, typename _Td>
-       requires __is_invocable_using<const decltype(__fn)&, _Td 
_GLIBCXX_MOF_CV*>
+      template< auto __cwfn, typename _Fn, typename _Td>
+       requires __is_invocable_using<const _Fn&, _Td _GLIBCXX_MOF_CV*>
        constexpr
-       function_ref(nontype_t<__fn>, _Td _GLIBCXX_MOF_CV* __ptr) noexcept
+       function_ref(constant_wrapper<__cwfn, _Fn>, _Td _GLIBCXX_MOF_CV* __ptr) 
noexcept
        {
-         using _Fn = remove_cv_t<decltype(__fn)>;
+         constexpr const _Fn& __fn = constant_wrapper<__cwfn, _Fn>::value;
          if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
            static_assert(__fn != nullptr);
          if constexpr (is_member_pointer_v<_Fn>)
@@ -182,8 +190,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }
 
       template<typename _Tp>
-       requires (!is_same_v<_Tp, function_ref>)
-              && (!is_pointer_v<_Tp>) && (!__is_nontype_v<_Tp>)
+       requires (!is_same_v<_Tp, function_ref>) && (!is_pointer_v<_Tp>)
+                && (!__is_constant_wrapper_v<_Tp>)
        function_ref&
        operator=(_Tp) = delete;
 
diff --git a/libstdc++-v3/include/bits/funcwrap.h 
b/libstdc++-v3/include/bits/funcwrap.h
index 6441893d2135..b835e075295b 100644
--- a/libstdc++-v3/include/bits/funcwrap.h
+++ b/libstdc++-v3/include/bits/funcwrap.h
@@ -573,15 +573,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     requires is_function_v<_Fn>
     function_ref(_Fn*) -> function_ref<_Fn>;
 
-  template<auto __f, class _Fn = remove_pointer_t<decltype(__f)>>
-    requires is_function_v<_Fn>
-    function_ref(nontype_t<__f>) -> function_ref<_Fn>;
+  template<auto __cwfn, typename _Fn>
+    requires is_function_v<remove_pointer_t<_Fn>>
+    function_ref(constant_wrapper<__cwfn, _Fn>)
+      -> function_ref<remove_pointer_t<_Fn>>;
 
-  template<auto __f, typename _Tp,
+  template<auto __cwfn, typename _Fn, typename _Tp,
           typename _SignaturePtr =
-            decltype(__polyfunc::__deduce_funcref<decltype(__f), _Tp&>())>
+            decltype(__polyfunc::__deduce_funcref<_Fn, _Tp&>())>
     requires (!is_void_v<_SignaturePtr>)
-    function_ref(nontype_t<__f>, _Tp&&)
+    function_ref(constant_wrapper<__cwfn, _Fn>, _Tp&&)
       -> function_ref<remove_pointer_t<_SignaturePtr>>;
 
 #endif // __glibcxx_function_ref
diff --git a/libstdc++-v3/include/bits/utility.h 
b/libstdc++-v3/include/bits/utility.h
index 970e63e81706..93e9e9f9dba2 100644
--- a/libstdc++-v3/include/bits/utility.h
+++ b/libstdc++-v3/include/bits/utility.h
@@ -458,6 +458,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { return value; }
   };
 
+  template<typename>
+    constexpr bool __is_constant_wrapper_v = false;
+
+  template<auto __cw, typename _Fn>
+    constexpr bool __is_constant_wrapper_v<constant_wrapper<__cw, _Fn>> = true;
+
   template<_CwFixedValue _Tp>
     constexpr auto cw = constant_wrapper<_Tp>{};
 #endif
@@ -637,23 +643,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline constexpr sorted_equivalent_t sorted_equivalent{};
 #endif
 
-#if __glibcxx_function_ref // >= C++26
-  template<auto>
-    struct nontype_t
-    {
-      explicit nontype_t() = default;
-    };
-
-  template<auto __val>
-    constexpr nontype_t<__val> nontype{};
-
-  template<typename>
-    inline constexpr bool __is_nontype_v = false;
-
-  template<auto __val>
-    inline constexpr bool __is_nontype_v<nontype_t<__val>> = true;
-#endif
-
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in
index db66677d55ba..3ac198716924 100644
--- a/libstdc++-v3/src/c++23/std.cc.in
+++ b/libstdc++-v3/src/c++23/std.cc.in
@@ -3651,10 +3651,6 @@ export namespace std
   using std::make_integer_sequence;
   using std::move;
   using std::move_if_noexcept;
-#if __cpp_lib_function_ref
-  using std::nontype_t;
-  using std::nontype;
-#endif
   using std::pair;
   using std::swap;
   using std::operator==;
diff --git a/libstdc++-v3/testsuite/20_util/function_ref/assign.cc 
b/libstdc++-v3/testsuite/20_util/function_ref/assign.cc
index 9b02dc49c2a3..521a35fc11e0 100644
--- a/libstdc++-v3/testsuite/20_util/function_ref/assign.cc
+++ b/libstdc++-v3/testsuite/20_util/function_ref/assign.cc
@@ -8,8 +8,7 @@
 # error "Feature-test macro for function_ref has wrong value in <functional>"
 #endif
 
-using std::nontype;
-using std::nontype_t;
+using std::constant_wrapper;
 using std::function_ref;
 
 using std::is_nothrow_move_assignable_v;
@@ -55,13 +54,13 @@ static_assert( ! is_assignable_v<function_ref<int(S)>, 
decltype(&S::x)> );
 static_assert( ! is_assignable_v<function_ref<int(S)>, decltype(&S::f)> );
 
 static_assert( is_nothrow_assignable_v<function_ref<int(S)>,
-                                      nontype_t<funS>> );
+                                      constant_wrapper<funS>> );
 static_assert( is_nothrow_assignable_v<function_ref<int(S)>,
-                                      nontype_t<&funS>> );
+                                      constant_wrapper<&funS>> );
 static_assert( is_nothrow_assignable_v<function_ref<int(S)>,
-                                      nontype_t<&S::x>> );
+                                      constant_wrapper<&S::x>> );
 static_assert( is_nothrow_assignable_v<function_ref<int(S)>,
-                                      nontype_t<&S::f>> );
+                                      constant_wrapper<&S::f>> );
 struct Q
 {
   void operator()() const;
@@ -75,22 +74,22 @@ static_assert( ! is_assignable_v<function_ref<void() 
const>, Q&> );
 static_assert( ! is_assignable_v<function_ref<void() const>, const Q&> );
 
 static_assert( is_nothrow_assignable_v<function_ref<void()>,
-                                      nontype_t<Q{}>> );
+                                      constant_wrapper<Q{}>> );
 static_assert( is_nothrow_assignable_v<function_ref<void() const>,
-                                      nontype_t<Q{}>> );
+                                      constant_wrapper<Q{}>> );
 
 constexpr bool
 test_constexpr()
 {
-  function_ref<void(S)> fp(nontype<funS>);
-  fp = nontype<funS>;
-  fp = nontype<&funS>;
-  fp = nontype<&S::x>;
-  fp = nontype<&S::f>;
+  function_ref<void(S)> fp(std::cw<funS>);
+  fp = std::cw<funS>;
+  fp = std::cw<&funS>;
+  fp = std::cw<&S::x>;
+  fp = std::cw<&S::f>;
 
   constexpr Q cq;
   function_ref<void() const> fq(cq);
-  fq = nontype<cq>;
+  fq = std::cw<cq>;
   return true;
 }
 static_assert( test_constexpr() );
diff --git a/libstdc++-v3/testsuite/20_util/function_ref/call.cc 
b/libstdc++-v3/testsuite/20_util/function_ref/call.cc
index 49c6030b221a..386c8de790ab 100644
--- a/libstdc++-v3/testsuite/20_util/function_ref/call.cc
+++ b/libstdc++-v3/testsuite/20_util/function_ref/call.cc
@@ -4,7 +4,6 @@
 #include <utility>
 #include <testsuite_hooks.h>
 
-using std::nontype;
 using std::function_ref;
 
 using std::is_same_v;
@@ -43,7 +42,7 @@ test01()
   VERIFY( f0() == 0 );
   VERIFY( std::move(f0)() == 0 );
 
-  function_ref<int()> f1{nontype<F{}>};
+  function_ref<int()> f1{std::cw<F{}>};
   VERIFY( f1() == 1 );
   VERIFY( std::move(f1)() == 1 );
 
@@ -53,7 +52,7 @@ test01()
   VERIFY( std::move(f2)() == 1 );
   VERIFY( std::move(std::as_const(f2))() == 1 );
 
-  function_ref<int() const> f3{nontype<F{}>};
+  function_ref<int() const> f3{std::cw<F{}>};
   VERIFY( f3() == 1 );
   VERIFY( std::as_const(f3)() == 1 );
   VERIFY( std::move(f3)() == 1 );
@@ -71,11 +70,11 @@ test02()
   };
   F::Arg arg;
 
-  function_ref<int()> f0{std::nontype<F{}>, arg};
+  function_ref<int()> f0{std::cw<F{}>, arg};
   VERIFY( f0() == 0 );
   VERIFY( std::move(f0)() == 0 );
 
-  function_ref<int() const> f1{std::nontype<F{}>, arg};
+  function_ref<int() const> f1{std::cw<F{}>, arg};
   VERIFY( f1() == 1 );
   VERIFY( std::as_const(f1)() == 1 );
 }
@@ -91,11 +90,11 @@ test03()
   };
   F::Arg arg;
 
-  function_ref<int()> f0{std::nontype<F{}>, &arg};
+  function_ref<int()> f0{std::cw<F{}>, &arg};
   VERIFY( f0() == 0 );
   VERIFY( std::move(f0)() == 0 );
 
-  function_ref<int() const> f1{std::nontype<F{}>, &arg};
+  function_ref<int() const> f1{std::cw<F{}>, &arg};
   VERIFY( f1() == 1 );
   VERIFY( std::as_const(f1)() == 1 );
 }
@@ -108,7 +107,7 @@ test04()
   VERIFY( f0() == 0 );
   VERIFY( std::move(f0)() == 0 );
 
-  function_ref<int()> f1{nontype<fp>};
+  function_ref<int()> f1{std::cw<fp>};
   VERIFY( f1() == 0 );
   VERIFY( std::move(f1)() == 0 );
 
@@ -116,7 +115,7 @@ test04()
   VERIFY( f2() == 0 );
   VERIFY( std::move(f2)() == 0 );
 
-  const function_ref<int() const> f3{nontype<fp>};
+  const function_ref<int() const> f3{std::cw<fp>};
   VERIFY( f2() == 0 );
   VERIFY( std::move(f2)() == 0 );
 }
@@ -130,14 +129,14 @@ int callback_ref(ftype& f, int x) { return f(x); }
 void
 test05()
 {
-  function_ref<int(int)> r1(nontype<&callback_ptr>, &twice);
+  function_ref<int(int)> r1(std::cw<&callback_ptr>, &twice);
   VERIFY( r1(2) == 4 );
-  function_ref<int(int)> r2(nontype<&callback_ptr>, cube);
+  function_ref<int(int)> r2(std::cw<&callback_ptr>, cube);
   VERIFY( r2(2) == 8 );
 
-  function_ref<int(int)> r3(nontype<&callback_ref>, twice);
+  function_ref<int(int)> r3(std::cw<&callback_ref>, twice);
   VERIFY( r3(3) == 6 );
-  function_ref<int(int)> r4(nontype<&callback_ref>, cube);
+  function_ref<int(int)> r4(std::cw<&callback_ref>, cube);
   VERIFY( r4(3) == 27 );
 }
 
@@ -174,37 +173,37 @@ test06()
   std::function_ref<const int&(int, int) const> e8(std::as_const(csr));
   VERIFY( &e8(0, 0) == &s.v );
 
-  std::function_ref<int&()> f1(std::nontype<&S::v>, sr);
+  std::function_ref<int&()> f1(std::cw<&S::v>, sr);
   VERIFY( &f1() == &s.v );
-  std::function_ref<const int&()> f2(std::nontype<&S::v>, sr);
+  std::function_ref<const int&()> f2(std::cw<&S::v>, sr);
   VERIFY( &f2() == &s.v );
-  std::function_ref<int&()> f3(std::nontype<&S::m>, sr);
+  std::function_ref<int&()> f3(std::cw<&S::m>, sr);
   VERIFY( &f3() == &s.v );
-  std::function_ref<const int&()> f4(std::nontype<&S::c>, sr);
+  std::function_ref<const int&()> f4(std::cw<&S::c>, sr);
   VERIFY( &f4() == &s.v );
 
-  std::function_ref<const int&()> f5(std::nontype<&S::v>, csr);
+  std::function_ref<const int&()> f5(std::cw<&S::v>, csr);
   VERIFY( &f5() == &s.v );
-  std::function_ref<const int&()> f6(std::nontype<&S::c>, sr);
+  std::function_ref<const int&()> f6(std::cw<&S::c>, sr);
   VERIFY( &f6() == &s.v );
   static_assert( !std::is_constructible_v<
     std::function_ref<int&()>,
-    std::nontype_t<&S::c>, std::reference_wrapper<S>&>
+    std::constant_wrapper<&S::c>, std::reference_wrapper<S>&>
    );
 
-  std::function_ref<int&()> f7(std::nontype<&S::v>, std::as_const(sr));
+  std::function_ref<int&()> f7(std::cw<&S::v>, std::as_const(sr));
   VERIFY( &f7() == &s.v );
-  std::function_ref<const int&()> f8(std::nontype<&S::m>, std::as_const(sr));
+  std::function_ref<const int&()> f8(std::cw<&S::m>, std::as_const(sr));
   VERIFY( &f8() == &s.v );
 
   // No rvalue reference_wrapper support
   static_assert( !std::is_constructible_v<
     std::function_ref<int&()>,
-    std::nontype_t<&S::v>, std::reference_wrapper<S>>
+    std::constant_wrapper<&S::v>, std::reference_wrapper<S>>
   );
   static_assert( !std::is_constructible_v<
     std::function_ref<int&()>,
-    std::nontype_t<&S::v>, std::reference_wrapper<const S>>
+    std::constant_wrapper<&S::v>, std::reference_wrapper<const S>>
   );
 
   // reference to reference_wrapper are bound, so mutation are visible
@@ -232,9 +231,9 @@ test06()
   { return &x; };
 
   // identity of reference_wrapper is preserved
-  std::function_ref<const std::reference_wrapper<S>*()> g1(std::nontype<id>, 
sr);
+  std::function_ref<const std::reference_wrapper<S>*()> g1(std::cw<id>, sr);
   VERIFY( g1() == &sr );
-  std::function_ref<const std::reference_wrapper<const S>*()> 
g2(std::nontype<id>, csr);
+  std::function_ref<const std::reference_wrapper<const S>*()> g2(std::cw<id>, 
csr);
   VERIFY( g2() == &csr );
 }
 
diff --git a/libstdc++-v3/testsuite/20_util/function_ref/cons.cc 
b/libstdc++-v3/testsuite/20_util/function_ref/cons.cc
index a91f5ba3dab2..78aebd38a074 100644
--- a/libstdc++-v3/testsuite/20_util/function_ref/cons.cc
+++ b/libstdc++-v3/testsuite/20_util/function_ref/cons.cc
@@ -9,8 +9,7 @@
 # error "Feature-test macro for function_ref has wrong value in <functional>"
 #endif
 
-using std::nontype;
-using std::nontype_t;
+using std::constant_wrapper;
 using std::function_ref;
 
 using std::is_default_constructible_v;
@@ -60,31 +59,31 @@ static_assert( ! is_constructible_v<function_ref<int(S)>,
                                    decltype(&S::f)> );
 
 static_assert( is_nothrow_constructible_v<function_ref<int(S)>,
-                                         nontype_t<funS>> );
+                                         constant_wrapper<funS>> );
 static_assert( is_nothrow_constructible_v<function_ref<int(S)>,
-                                         nontype_t<&funS>> );
+                                         constant_wrapper<&funS>> );
 static_assert( is_nothrow_constructible_v<function_ref<int(S)>,
-                                         nontype_t<&S::x>> );
+                                         constant_wrapper<&S::x>> );
 static_assert( is_nothrow_constructible_v<function_ref<int(S)>,
-                                         nontype_t<&S::f>> );
+                                         constant_wrapper<&S::f>> );
 
 static_assert( is_nothrow_constructible_v<function_ref<int()>,
-                                         nontype_t<funS>, S&> );
+                                         constant_wrapper<funS>, S&> );
 static_assert( is_nothrow_constructible_v<function_ref<int()>,
-                                         nontype_t<&funS>, S&> );
+                                         constant_wrapper<&funS>, S&> );
 static_assert( is_nothrow_constructible_v<function_ref<int()>,
-                                         nontype_t<&S::x>, S&> );
+                                         constant_wrapper<&S::x>, S&> );
 static_assert( is_nothrow_constructible_v<function_ref<int()>,
-                                         nontype_t<&S::f>, S&> );
+                                         constant_wrapper<&S::f>, S&> );
 
 static_assert( ! is_constructible_v<function_ref<int()>,
-                                   nontype_t<funS>, S*> );
+                                   constant_wrapper<funS>, S*> );
 static_assert( ! is_constructible_v<function_ref<int()>,
-                                   nontype_t<&funS>, S*> );
+                                   constant_wrapper<&funS>, S*> );
 static_assert( is_nothrow_constructible_v<function_ref<int()>,
-                                         nontype_t<&S::x>, S*> );
+                                         constant_wrapper<&S::x>, S*> );
 static_assert( is_nothrow_constructible_v<function_ref<int()>,
-                                         nontype_t<&S::f>, S*> );
+                                         constant_wrapper<&S::f>, S*> );
 
 struct M
 {
@@ -98,9 +97,9 @@ static_assert( ! is_constructible_v<function_ref<void()>, 
const M&> );
 static_assert( ! is_constructible_v<function_ref<void() const>, M> );
 static_assert( ! is_constructible_v<function_ref<void() const>, const M&> );
 static_assert( ! is_constructible_v<function_ref<void()>,
-                                   nontype_t<M{}>> );
+                                   constant_wrapper<M{}>> );
 static_assert( ! is_constructible_v<function_ref<void() const>,
-                                   nontype_t<M{}>> );
+                                   constant_wrapper<M{}>> );
 struct Q
 {
   void operator()(int) const;
@@ -115,22 +114,22 @@ static_assert( 
is_nothrow_constructible_v<function_ref<void(int) const>, Q&> );
 static_assert( is_nothrow_constructible_v<function_ref<void(int) const>, const 
Q&> );
 
 static_assert( is_nothrow_constructible_v<function_ref<void(int)>,
-                                         nontype_t<Q{}>> );
+                                         constant_wrapper<Q{}>> );
 static_assert( is_nothrow_constructible_v<function_ref<void(int) const>,
-                                         nontype_t<Q{}>> );
+                                         constant_wrapper<Q{}>> );
 static_assert( is_nothrow_constructible_v<function_ref<void()>,
-                                         nontype_t<Q{}>, int&> );
+                                         constant_wrapper<Q{}>, int&> );
 static_assert( is_nothrow_constructible_v<function_ref<void() const>,
-                                         nontype_t<Q{}>, int&> );
+                                         constant_wrapper<Q{}>, int&> );
 static_assert( ! is_constructible_v<function_ref<void()>,
-                                   nontype_t<Q{}>, int> );
+                                   constant_wrapper<Q{}>, int> );
 static_assert( ! is_constructible_v<function_ref<void() const>,
-                                   nontype_t<Q{}>, int> );
+                                   constant_wrapper<Q{}>, int> );
 
 static_assert( is_nothrow_constructible_v<function_ref<void()>,
-                                         nontype_t<Q{}>, int*> );
+                                         constant_wrapper<Q{}>, int*> );
 static_assert( ! is_constructible_v<function_ref<void() const>,
-                                   nontype_t<Q{}>, int*> );
+                                   constant_wrapper<Q{}>, int*> );
 
 struct L
 {
@@ -143,9 +142,9 @@ static_assert( ! is_constructible_v<function_ref<void()>, 
const L&> );
 static_assert( ! is_constructible_v<function_ref<void() const>, L> );
 static_assert( ! is_constructible_v<function_ref<void() const>, const L&> );
 static_assert( ! is_constructible_v<function_ref<void()>,
-                                   nontype_t<L{}>> );
+                                   constant_wrapper<L{}>> );
 static_assert( ! is_constructible_v<function_ref<void() const>,
-                                   nontype_t<L{}>> );
+                                   constant_wrapper<L{}>> );
 
 struct R
 {
@@ -159,24 +158,24 @@ static_assert( ! 
is_constructible_v<function_ref<void(float) const>, R&> );
 static_assert( ! is_constructible_v<function_ref<void(float) const>, const R&> 
);
 
 static_assert( ! is_constructible_v<function_ref<void(float)>,
-                                                nontype_t<R{}>> );
+                                   constant_wrapper<R{}>> );
 static_assert( ! is_constructible_v<function_ref<void(float) const>,
-                                                nontype_t<R{}>> );
+                                   constant_wrapper<R{}>> );
 
 constexpr bool
 test_constexpr()
 {
-  function_ref<void(S)> fp1(nontype<funS>);
-  function_ref<void(S)> fp3(nontype<&funS>);
-  function_ref<void(S)> fp4(nontype<&S::x>);
-  function_ref<void(S)> fp5(nontype<&S::f>);
+  function_ref<void(S)> fp1(std::cw<funS>);
+  function_ref<void(S)> fp3(std::cw<&funS>);
+  function_ref<void(S)> fp4(std::cw<&S::x>);
+  function_ref<void(S)> fp5(std::cw<&S::f>);
 
   S s;
-  function_ref<void()> fp6(nontype<&funS>, s);
-  function_ref<void()> fp7(nontype<&S::x>, s);
-  function_ref<void()> fp8(nontype<&S::x>, &s);
-  function_ref<void()> fp9(nontype<&S::f>, s);
-  function_ref<void()> fp10(nontype<&S::f>, &s);
+  function_ref<void()> fp6(std::cw<&funS>, s);
+  function_ref<void()> fp7(std::cw<&S::x>, s);
+  function_ref<void()> fp8(std::cw<&S::x>, &s);
+  function_ref<void()> fp9(std::cw<&S::f>, s);
+  function_ref<void()> fp10(std::cw<&S::f>, &s);
 
   M m;
   function_ref<void()> fm1(m);
@@ -190,13 +189,13 @@ test_constexpr()
 
   function_ref<void(int)> fcq1(cq);
   function_ref<void(int) const> f(cq);
-  function_ref<void(int)> fcq3(nontype<cq>);
-  function_ref<void(int) const> fcq4(nontype<cq>);
+  function_ref<void(int)> fcq3(std::cw<cq>);
+  function_ref<void(int) const> fcq4(std::cw<cq>);
 
   int i = 0;
-  function_ref<void()> fcq5(nontype<cq>, i);
-  function_ref<void() const> fcq6(nontype<cq>, i);
-  function_ref<void()> fcq7(nontype<cq>, &i);
+  function_ref<void()> fcq5(std::cw<cq>, i);
+  function_ref<void() const> fcq6(std::cw<cq>, i);
+  function_ref<void()> fcq7(std::cw<cq>, &i);
 
   L l;
   function_ref<void()> fl1(l);
diff --git a/libstdc++-v3/testsuite/20_util/function_ref/cons_neg.cc 
b/libstdc++-v3/testsuite/20_util/function_ref/cons_neg.cc
index 050090df3704..a426ac64cd53 100644
--- a/libstdc++-v3/testsuite/20_util/function_ref/cons_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/function_ref/cons_neg.cc
@@ -2,7 +2,6 @@
 
 #include <functional>
 
-using std::nontype;
 using std::function_ref;
 
 struct S
@@ -16,15 +15,15 @@ constexpr int(*fp)(S) = nullptr;
 constexpr int S::*mdp = nullptr;
 constexpr int (S::*mfp)() = nullptr;
 
-function_ref<int(S)> fd1(nontype<fp>);  // { dg-error "from here" }
-function_ref<int(S)> fd2(nontype<mdp>); // { dg-error "from here" }
-function_ref<int(S)> fd3(nontype<mfp>); // { dg-error "from here" }
+function_ref<int(S)> fd1(std::cw<fp>);  // { dg-error "from here" }
+function_ref<int(S)> fd2(std::cw<mdp>); // { dg-error "from here" }
+function_ref<int(S)> fd3(std::cw<mfp>); // { dg-error "from here" }
 
-function_ref<int()> br4(nontype<fp>, s);  // { dg-error "from here" }
-function_ref<int()> br5(nontype<mdp>, s); // { dg-error "from here" }
-function_ref<int()> br6(nontype<mfp>, s); // { dg-error "from here" }
+function_ref<int()> br4(std::cw<fp>, s);  // { dg-error "from here" }
+function_ref<int()> br5(std::cw<mdp>, s); // { dg-error "from here" }
+function_ref<int()> br6(std::cw<mfp>, s); // { dg-error "from here" }
 
-function_ref<int()> bp7(nontype<mdp>, &s); // { dg-error "from here" }
-function_ref<int()> bp8(nontype<mfp>, &s); // { dg-error "from here" }
+function_ref<int()> bp7(std::cw<mdp>, &s); // { dg-error "from here" }
+function_ref<int()> bp8(std::cw<mfp>, &s); // { dg-error "from here" }
 
 // { dg-prune-output "static assertion failed" }
diff --git a/libstdc++-v3/testsuite/20_util/function_ref/cw_cons_neg.cc 
b/libstdc++-v3/testsuite/20_util/function_ref/cw_cons_neg.cc
new file mode 100644
index 000000000000..a295bc2ce31d
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/function_ref/cw_cons_neg.cc
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++26 } }
+
+#include <functional>
+
+using std::function_ref;
+using std::constant_wrapper;
+
+struct S
+{
+  int operator()() const { return 1; }
+
+  // Non-constant, so cw<S{}>(cw<1>) call never unwrapps
+  int operator()(int) const { return 1; }
+  template<auto __cw>
+    int operator()(constant_wrapper<__cw, int>) const { return 1; }
+
+  // Constant, cw<S{}>(cw<1>, cw<2>) calls int overload
+  // while S{}(cw<1>, cw<1>) calls constant_wrapper overload
+  constexpr int operator()(int, int) const { return 1; }
+  template<auto __cw1, auto __cw2>
+    constexpr int operator()(constant_wrapper<__cw1, int>,
+                            constant_wrapper<__cw2, int>)
+    { return 1; }
+};
+
+function_ref<int()> f0a(S{});
+
+function_ref<int(int)> f1a(S{});
+function_ref<int(constant_wrapper<2>)> f1b(std::cw<S{}>);
+
+function_ref<int(int, int)> f2a(std::cw<S{}>); // OK, runtime
+function_ref<int(constant_wrapper<1>, int)> f2b(std::cw<S{}>); // OK, still 
runtime
+function_ref<int(constant_wrapper<2>, constant_wrapper<3>)> f2c(std::cw<S{}>); 
// { dg-error "from here" }
+
+// { dg-prune-output "static assertion failed" }
diff --git a/libstdc++-v3/testsuite/20_util/function_ref/dangling.cc 
b/libstdc++-v3/testsuite/20_util/function_ref/dangling.cc
index 3cc782524f6e..4ef5d067555d 100644
--- a/libstdc++-v3/testsuite/20_util/function_ref/dangling.cc
+++ b/libstdc++-v3/testsuite/20_util/function_ref/dangling.cc
@@ -46,7 +46,7 @@ struct NonStatic {
   { return x + y + v; }
 };
 
-constexpr auto vNonType = create(std::nontype<NonStatic{3}>);
+constexpr auto vNonType = create(std::cw<NonStatic{3}>);
 
 struct StaticWins {
   static int
diff --git a/libstdc++-v3/testsuite/20_util/function_ref/deduction.cc 
b/libstdc++-v3/testsuite/20_util/function_ref/deduction.cc
index b034c7af0725..63c3f6ea7e3c 100644
--- a/libstdc++-v3/testsuite/20_util/function_ref/deduction.cc
+++ b/libstdc++-v3/testsuite/20_util/function_ref/deduction.cc
@@ -4,15 +4,13 @@
 #include <type_traits>
 
 using std::is_same_v;
-using std::nontype;
-using std::nontype_t;
 using std::function_ref;
 
 int i = 0;
 
 template<auto f, class... Args>
   concept deductible = requires (Args&... args) 
-  { std::function_ref(std::nontype<f>, args...); };
+  { std::function_ref(std::cw<f>, args...); };
 
 static_assert( !deductible<1> );
 static_assert( !deductible<1, int> );
@@ -24,9 +22,9 @@ static_assert( is_same_v<decltype(function_ref(f0)),
                         function_ref<void()>> );
 static_assert( is_same_v<decltype(function_ref(f0n)),
                         function_ref<void() noexcept>> );
-static_assert( is_same_v<decltype(function_ref(nontype<f0>)),
+static_assert( is_same_v<decltype(function_ref(std::cw<f0>)),
                         function_ref<void()>> );
-static_assert( is_same_v<decltype(function_ref(nontype<f0n>)),
+static_assert( is_same_v<decltype(function_ref(std::cw<f0n>)),
                         function_ref<void() noexcept>> );
 static_assert( !deductible<f0, char*> );
 static_assert( !deductible<f0n, char*> );
@@ -38,13 +36,13 @@ static_assert( is_same_v<decltype(function_ref(f1)),
                         function_ref<void(int)>> );
 static_assert( is_same_v<decltype(function_ref(f1n)),
                         function_ref<void(int) noexcept>> );
-static_assert( is_same_v<decltype(function_ref(nontype<f1>)),
+static_assert( is_same_v<decltype(function_ref(std::cw<f1>)),
                         function_ref<void(int)>> );
-static_assert( is_same_v<decltype(function_ref(nontype<f1n>)),
+static_assert( is_same_v<decltype(function_ref(std::cw<f1n>)),
                         function_ref<void(int) noexcept>> );
-static_assert( is_same_v<decltype(function_ref(nontype<f1>, i)),
+static_assert( is_same_v<decltype(function_ref(std::cw<f1>, i)),
                         function_ref<void()>> );
-static_assert( is_same_v<decltype(function_ref(nontype<f1n>, i)),
+static_assert( is_same_v<decltype(function_ref(std::cw<f1n>, i)),
                         function_ref<void() noexcept>> );
 static_assert( !deductible<f1, char*> );
 static_assert( !deductible<f1n, char*> );
@@ -56,13 +54,13 @@ static_assert( is_same_v<decltype(function_ref(f2)),
                         function_ref<void(int*, int)>> );
 static_assert( is_same_v<decltype(function_ref(f2n)),
                         function_ref<void(int*, int) noexcept>> );
-static_assert( is_same_v<decltype(function_ref(nontype<f2>)),
+static_assert( is_same_v<decltype(function_ref(std::cw<f2>)),
                         function_ref<void(int*, int)>> );
-static_assert( is_same_v<decltype(function_ref(nontype<f2n>)),
+static_assert( is_same_v<decltype(function_ref(std::cw<f2n>)),
                         function_ref<void(int*, int) noexcept>> );
-static_assert( is_same_v<decltype(function_ref(nontype<f2>, &i)),
+static_assert( is_same_v<decltype(function_ref(std::cw<f2>, &i)),
                         function_ref<void(int)>> );
-static_assert( is_same_v<decltype(function_ref(nontype<f2n>, &i)),
+static_assert( is_same_v<decltype(function_ref(std::cw<f2n>, &i)),
                         function_ref<void(int) noexcept>> );
 static_assert( !deductible<f2, char*> );
 static_assert( !deductible<f2n, char*> );
@@ -88,40 +86,40 @@ struct S
 S s{};
 const S cs{};
 
-static_assert( is_same_v<decltype(function_ref(nontype<&S::mem>, s)),
+static_assert( is_same_v<decltype(function_ref(std::cw<&S::mem>, s)),
                         function_ref<int&() noexcept>> );
-static_assert( is_same_v<decltype(function_ref(nontype<&S::mem>, cs)),
+static_assert( is_same_v<decltype(function_ref(std::cw<&S::mem>, cs)),
                         function_ref<const int&() noexcept>> );
-static_assert( is_same_v<decltype(function_ref(nontype<&S::mem>, &s)),
+static_assert( is_same_v<decltype(function_ref(std::cw<&S::mem>, &s)),
                         function_ref<int&() noexcept>> );
-static_assert( is_same_v<decltype(function_ref(nontype<&S::mem>, &cs)),
+static_assert( is_same_v<decltype(function_ref(std::cw<&S::mem>, &cs)),
                         function_ref<const int&() noexcept>> );
 static_assert( !deductible<&S::mem, int> );
 
-static_assert( is_same_v<decltype(function_ref(nontype<&S::f>, s)),
+static_assert( is_same_v<decltype(function_ref(std::cw<&S::f>, s)),
                         function_ref<int()>> );
-static_assert( is_same_v<decltype(function_ref(nontype<&S::fn>, &s)),
+static_assert( is_same_v<decltype(function_ref(std::cw<&S::fn>, &s)),
                         function_ref<int() noexcept>> );
 static_assert( !deductible<&S::f, char*> );
 static_assert( !deductible<&S::fn, char*> );
 static_assert( !deductible<&S::f, const S> );
 static_assert( !deductible<&S::fn, const S> );
 
-static_assert( is_same_v<decltype(function_ref(nontype<&S::fc>, &s)),
+static_assert( is_same_v<decltype(function_ref(std::cw<&S::fc>, &s)),
                         function_ref<int(int)>> );
-static_assert( is_same_v<decltype(function_ref(nontype<&S::fcn>, s)),
+static_assert( is_same_v<decltype(function_ref(std::cw<&S::fcn>, s)),
                         function_ref<int(int) noexcept>> );
 static_assert( !deductible<&S::fc, char*> );
 static_assert( !deductible<&S::fcn, char*> );
 
-static_assert( is_same_v<decltype(function_ref(nontype<&S::fl>, &s)),
+static_assert( is_same_v<decltype(function_ref(std::cw<&S::fl>, &s)),
                         function_ref<int(int)>> );
-static_assert( is_same_v<decltype(function_ref(nontype<&S::fln>, s)),
+static_assert( is_same_v<decltype(function_ref(std::cw<&S::fln>, s)),
                         function_ref<int(int) noexcept>> );
 
-static_assert( is_same_v<decltype(function_ref(nontype<&S::fcl>, s)),
+static_assert( is_same_v<decltype(function_ref(std::cw<&S::fcl>, s)),
                         function_ref<int(float)>> );
-static_assert( is_same_v<decltype(function_ref(nontype<&S::fcln>, &s)),
+static_assert( is_same_v<decltype(function_ref(std::cw<&S::fcln>, &s)),
                         function_ref<int(float) noexcept>> );
 
 static_assert( !deductible<&S::fr, char*> );
diff --git a/libstdc++-v3/testsuite/20_util/function_ref/mutation.cc 
b/libstdc++-v3/testsuite/20_util/function_ref/mutation.cc
index 32c6931e9a80..d55f4facbda1 100644
--- a/libstdc++-v3/testsuite/20_util/function_ref/mutation.cc
+++ b/libstdc++-v3/testsuite/20_util/function_ref/mutation.cc
@@ -3,7 +3,6 @@
 #include <functional>
 #include <testsuite_hooks.h>
 
-using std::nontype;
 using std::function_ref;
 
 void
@@ -55,8 +54,8 @@ test02()
   };
   S s{10};
 
-  function_ref<int()> r1(nontype<&S::x>, s);
-  function_ref<long()> r2(nontype<&S::x>, &s);
+  function_ref<int()> r1(std::cw<&S::x>, s);
+  function_ref<long()> r2(std::cw<&S::x>, &s);
 
   VERIFY( r1() == 10 );
   VERIFY( r2() == 10 );
@@ -66,8 +65,8 @@ test02()
   VERIFY( r1() == 20 );
   VERIFY( r2() == 20 );
 
-  r1 = function_ref<int()>(nontype<&S::f>, &s);
-  r2 = function_ref<long()>(nontype<&S::f>, s);
+  r1 = function_ref<int()>(std::cw<&S::f>, &s);
+  r2 = function_ref<long()>(std::cw<&S::f>, s);
 
   VERIFY( r1() == 20 );
   VERIFY( r2() == 20 );

Reply via email to