[PATCH] libstdc++: Remove non_type and replace it with constant_wrapper in function_ref
Tomasz Kaminski
tkaminsk@redhat.com
Wed Apr 8 12:56:09 GMT 2026
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
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260408/832a7720/attachment-0001.htm>
More information about the Libstdc++
mailing list