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