libstdc++: Remove non_type and replace it with constant_wrapper in function_ref

Message ID 20260408094553.155396-1-tkaminsk@redhat.com
State New
Headers
Series libstdc++: Remove non_type and replace it with constant_wrapper in function_ref |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 fail Patch failed to apply

Commit Message

Tomasz Kaminski April 8, 2026, 9:27 a.m. UTC
  From: Matthias Kretz <m.kretz@gsi.de>

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_refoperator=): Detect constant_wrapper rather than
	nontype_t.
	* include/bits/funcwrap.h (function_ref): Change
	* include/bits/utility.h (std::nontype_t, std::nontype)
	(std::__is_nontype_v): Remove.
	(_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/deduction.cc: Likewise.
	* testsuite/20_util/function_ref/mutation.cc: Likewise.

Co-authored-by: Tomasz Kamiński <tkaminsk@redhat.com>
Signed-off-by: Matthias Kretz <m.kretz@gsi.de>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
---
This is based on Matthias patch from formge:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/147/commits/cac7355bcbd7ea8b5e26f064922e8f4412a4da97

I have applied small adjustment to names and parameter specification,
to be more consistient with the standard. Outside of that I have reworked
static_assert to reflect more closely what is in the standard, and added
negative test (cw_const_neg.cc).

Testing on x86_64-linux. All *function_ref* test already passed in
all standard modes and with modules. OK for trunk when all test passes?


 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 +++++++++----------
 .../20_util/function_ref/cons_neg.cc          | 17 ++--
 .../20_util/function_ref/cw_cons_neg.cc       | 35 ++++++++
 .../20_util/function_ref/dangling.cc          |  2 +-
 .../20_util/function_ref/deduction.cc         | 48 +++++------
 .../20_util/function_ref/mutation.cc          |  9 +-
 12 files changed, 185 insertions(+), 163 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/20_util/function_ref/cw_cons_neg.cc
  

Comments

Jonathan Wakely April 8, 2026, 10:04 a.m. UTC | #1
On Wed, 8 Apr 2026, 10:46 Tomasz Kamiński, <tkaminsk@redhat.com> wrote:

> From: Matthias Kretz <m.kretz@gsi.de>
>
> 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_refoperator=): Detect constant_wrapper rather than
>         nontype_t.
>

Missing :: here

        * include/bits/funcwrap.h (function_ref): Change
>         * include/bits/utility.h (std::nontype_t, std::nontype)
>         (std::__is_nontype_v): Remove.
>         (_is_constant_wrapper_v): Define.
>

And _ here

The patch itself is fine, so OK with those two tweaks to the changelog.


        * 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/deduction.cc: Likewise.
>         * testsuite/20_util/function_ref/mutation.cc: Likewise.
>
> Co-authored-by: Tomasz Kamiński <tkaminsk@redhat.com>
> Signed-off-by: Matthias Kretz <m.kretz@gsi.de>
> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
> ---
> This is based on Matthias patch from formge:
>
> https://forge.sourceware.org/gcc/gcc-TEST/pulls/147/commits/cac7355bcbd7ea8b5e26f064922e8f4412a4da97
>
> I have applied small adjustment to names and parameter specification,
> to be more consistient with the standard. Outside of that I have reworked
> static_assert to reflect more closely what is in the standard, and added
> negative test (cw_const_neg.cc).
>
> Testing on x86_64-linux. All *function_ref* test already passed in
> all standard modes and with modules. OK for trunk when all test passes?
>
>
>  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 +++++++++----------
>  .../20_util/function_ref/cons_neg.cc          | 17 ++--
>  .../20_util/function_ref/cw_cons_neg.cc       | 35 ++++++++
>  .../20_util/function_ref/dangling.cc          |  2 +-
>  .../20_util/function_ref/deduction.cc         | 48 +++++------
>  .../20_util/function_ref/mutation.cc          |  9 +-
>  12 files changed, 185 insertions(+), 163 deletions(-)
>  create mode 100644
> libstdc++-v3/testsuite/20_util/function_ref/cw_cons_neg.cc
>
> diff --git a/libstdc++-v3/include/bits/funcref_impl.h
> b/libstdc++-v3/include/bits/funcref_impl.h
> index 3d55c8406b0..9fcab570803 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 6441893d213..b835e075295 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 970e63e8170..93e9e9f9dba 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 db66677d55b..3ac19871692 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 9b02dc49c2a..521a35fc11e 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 49c6030b221..386c8de790a 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 a91f5ba3dab..78aebd38a07 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 050090df370..a426ac64cd5 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 00000000000..a295bc2ce31
> --- /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 3cc782524f6..4ef5d067555 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 b034c7af072..63c3f6ea7e3 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 32c6931e9a8..d55f4facbda 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 );
> --
> 2.53.0
>
>
  
Tomasz Kaminski April 8, 2026, 12:56 p.m. UTC | #2
I have forgotten to bump function_ref FTM, but that turned out to be good
thing, because we have another paper
bumping it at the same time:
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3961r0.html
Should we use 202304L for the second paper? They seem separable, but we
will inflict some order.


On Wed, Apr 8, 2026 at 12:04 PM Jonathan Wakely <jwakely.gcc@gmail.com>
wrote:

>
>
> On Wed, 8 Apr 2026, 10:46 Tomasz Kamiński, <tkaminsk@redhat.com> wrote:
>
>> From: Matthias Kretz <m.kretz@gsi.de>
>>
>> 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_refoperator=): Detect constant_wrapper rather than
>>         nontype_t.
>>
>
> Missing :: here
>
>         * include/bits/funcwrap.h (function_ref): Change
>>         * include/bits/utility.h (std::nontype_t, std::nontype)
>>         (std::__is_nontype_v): Remove.
>>         (_is_constant_wrapper_v): Define.
>>
>
> And _ here
>
> The patch itself is fine, so OK with those two tweaks to the changelog.
>
>
>         * 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/deduction.cc: Likewise.
>>         * testsuite/20_util/function_ref/mutation.cc: Likewise.
>>
>> Co-authored-by: Tomasz Kamiński <tkaminsk@redhat.com>
>> Signed-off-by: Matthias Kretz <m.kretz@gsi.de>
>> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
>> ---
>> This is based on Matthias patch from formge:
>>
>> https://forge.sourceware.org/gcc/gcc-TEST/pulls/147/commits/cac7355bcbd7ea8b5e26f064922e8f4412a4da97
>>
>> I have applied small adjustment to names and parameter specification,
>> to be more consistient with the standard. Outside of that I have reworked
>> static_assert to reflect more closely what is in the standard, and added
>> negative test (cw_const_neg.cc).
>>
>> Testing on x86_64-linux. All *function_ref* test already passed in
>> all standard modes and with modules. OK for trunk when all test passes?
>>
>>
>>  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 +++++++++----------
>>  .../20_util/function_ref/cons_neg.cc          | 17 ++--
>>  .../20_util/function_ref/cw_cons_neg.cc       | 35 ++++++++
>>  .../20_util/function_ref/dangling.cc          |  2 +-
>>  .../20_util/function_ref/deduction.cc         | 48 +++++------
>>  .../20_util/function_ref/mutation.cc          |  9 +-
>>  12 files changed, 185 insertions(+), 163 deletions(-)
>>  create mode 100644
>> libstdc++-v3/testsuite/20_util/function_ref/cw_cons_neg.cc
>>
>> diff --git a/libstdc++-v3/include/bits/funcref_impl.h
>> b/libstdc++-v3/include/bits/funcref_impl.h
>> index 3d55c8406b0..9fcab570803 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 6441893d213..b835e075295 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 970e63e8170..93e9e9f9dba 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 db66677d55b..3ac19871692 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 9b02dc49c2a..521a35fc11e 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 49c6030b221..386c8de790a 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 a91f5ba3dab..78aebd38a07 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 050090df370..a426ac64cd5 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 00000000000..a295bc2ce31
>> --- /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 3cc782524f6..4ef5d067555 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 b034c7af072..63c3f6ea7e3 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 32c6931e9a8..d55f4facbda 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 );
>> --
>> 2.53.0
>>
>>
  
Jonathan Wakely April 8, 2026, 3:24 p.m. UTC | #3
On Wed, 8 Apr 2026, 13:56 Tomasz Kaminski, <tkaminsk@redhat.com> wrote:

> I have forgotten to bump function_ref FTM, but that turned out to be good
> thing, because we have another paper
> bumping it at the same time:
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3961r0.html
> Should we use 202304L for the second paper?
>

Yes that makes sense. Barry and I agree on behalf of sg10.


They seem separable, but we will inflict some order.
>
>
> On Wed, Apr 8, 2026 at 12:04 PM Jonathan Wakely <jwakely.gcc@gmail.com>
> wrote:
>
>>
>>
>> On Wed, 8 Apr 2026, 10:46 Tomasz Kamiński, <tkaminsk@redhat.com> wrote:
>>
>>> From: Matthias Kretz <m.kretz@gsi.de>
>>>
>>> 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_refoperator=): Detect constant_wrapper rather than
>>>         nontype_t.
>>>
>>
>> Missing :: here
>>
>>         * include/bits/funcwrap.h (function_ref): Change
>>>         * include/bits/utility.h (std::nontype_t, std::nontype)
>>>         (std::__is_nontype_v): Remove.
>>>         (_is_constant_wrapper_v): Define.
>>>
>>
>> And _ here
>>
>> The patch itself is fine, so OK with those two tweaks to the changelog.
>>
>>
>>         * 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/deduction.cc: Likewise.
>>>         * testsuite/20_util/function_ref/mutation.cc: Likewise.
>>>
>>> Co-authored-by: Tomasz Kamiński <tkaminsk@redhat.com>
>>> Signed-off-by: Matthias Kretz <m.kretz@gsi.de>
>>> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
>>> ---
>>> This is based on Matthias patch from formge:
>>>
>>> https://forge.sourceware.org/gcc/gcc-TEST/pulls/147/commits/cac7355bcbd7ea8b5e26f064922e8f4412a4da97
>>>
>>> I have applied small adjustment to names and parameter specification,
>>> to be more consistient with the standard. Outside of that I have reworked
>>> static_assert to reflect more closely what is in the standard, and added
>>> negative test (cw_const_neg.cc).
>>>
>>> Testing on x86_64-linux. All *function_ref* test already passed in
>>> all standard modes and with modules. OK for trunk when all test passes?
>>>
>>>
>>>  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 +++++++++----------
>>>  .../20_util/function_ref/cons_neg.cc          | 17 ++--
>>>  .../20_util/function_ref/cw_cons_neg.cc       | 35 ++++++++
>>>  .../20_util/function_ref/dangling.cc          |  2 +-
>>>  .../20_util/function_ref/deduction.cc         | 48 +++++------
>>>  .../20_util/function_ref/mutation.cc          |  9 +-
>>>  12 files changed, 185 insertions(+), 163 deletions(-)
>>>  create mode 100644
>>> libstdc++-v3/testsuite/20_util/function_ref/cw_cons_neg.cc
>>>
>>> diff --git a/libstdc++-v3/include/bits/funcref_impl.h
>>> b/libstdc++-v3/include/bits/funcref_impl.h
>>> index 3d55c8406b0..9fcab570803 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 6441893d213..b835e075295 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 970e63e8170..93e9e9f9dba 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 db66677d55b..3ac19871692 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 9b02dc49c2a..521a35fc11e 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 49c6030b221..386c8de790a 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 a91f5ba3dab..78aebd38a07 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 050090df370..a426ac64cd5 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 00000000000..a295bc2ce31
>>> --- /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 3cc782524f6..4ef5d067555 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 b034c7af072..63c3f6ea7e3 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 32c6931e9a8..d55f4facbda 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 );
>>> --
>>> 2.53.0
>>>
>>>
  

Patch

diff --git a/libstdc++-v3/include/bits/funcref_impl.h b/libstdc++-v3/include/bits/funcref_impl.h
index 3d55c8406b0..9fcab570803 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 6441893d213..b835e075295 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 970e63e8170..93e9e9f9dba 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 db66677d55b..3ac19871692 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 9b02dc49c2a..521a35fc11e 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 49c6030b221..386c8de790a 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 a91f5ba3dab..78aebd38a07 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 050090df370..a426ac64cd5 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 00000000000..a295bc2ce31
--- /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 3cc782524f6..4ef5d067555 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 b034c7af072..63c3f6ea7e3 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 32c6931e9a8..d55f4facbda 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 );