diff --git a/libcxx/docs/Cxx2aStatusPaperStatus.csv b/libcxx/docs/Cxx2aStatusPaperStatus.csv --- a/libcxx/docs/Cxx2aStatusPaperStatus.csv +++ b/libcxx/docs/Cxx2aStatusPaperStatus.csv @@ -109,7 +109,7 @@ "`P0980 `__","LWG","Making std::string constexpr","Cologne","","" "`P1004 `__","LWG","Making std::vector constexpr","Cologne","","" "`P1035 `__","LWG","Input Range Adaptors","Cologne","","" -"`P1065 `__","LWG","Constexpr INVOKE","Cologne","","" +"`P1065 `__","LWG","Constexpr INVOKE","Cologne","|Complete|","12.0" "`P1135 `__","LWG","The C++20 Synchronization Library","Cologne","|Complete|","11.0" "`P1207 `__","LWG","Movability of Single-pass Iterators","Cologne","","" "`P1208 `__","LWG","Adopt source_location for C++20","Cologne","","" diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -194,7 +194,7 @@ ------------------------------------------------- ----------------- ``__cpp_lib_constexpr_dynamic_alloc`` ``201907L`` ------------------------------------------------- ----------------- - ``__cpp_lib_constexpr_misc`` *unimplemented* + ``__cpp_lib_constexpr_functional`` ``201907L`` ------------------------------------------------- ----------------- ``__cpp_lib_constexpr_numeric`` ``201911L`` ------------------------------------------------- ----------------- diff --git a/libcxx/include/__functional_base b/libcxx/include/__functional_base --- a/libcxx/include/__functional_base +++ b/libcxx/include/__functional_base @@ -382,20 +382,23 @@ public: // construct/copy/destroy - _LIBCPP_INLINE_VISIBILITY reference_wrapper(type& __f) _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + reference_wrapper(type& __f) _NOEXCEPT : __f_(_VSTD::addressof(__f)) {} #ifndef _LIBCPP_CXX03_LANG private: reference_wrapper(type&&); public: // = delete; // do not bind to temps #endif // access - _LIBCPP_INLINE_VISIBILITY operator type& () const _NOEXCEPT {return *__f_;} - _LIBCPP_INLINE_VISIBILITY type& get() const _NOEXCEPT {return *__f_;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + operator type& () const _NOEXCEPT {return *__f_;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + type& get() const _NOEXCEPT {return *__f_;} #ifndef _LIBCPP_CXX03_LANG // invoke template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename __invoke_of::type operator() (_ArgTypes&&... __args) const { return _VSTD::__invoke(get(), _VSTD::forward<_ArgTypes>(__args)...); @@ -510,7 +513,7 @@ template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference_wrapper<_Tp> ref(_Tp& __t) _NOEXCEPT { @@ -518,7 +521,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference_wrapper<_Tp> ref(reference_wrapper<_Tp> __t) _NOEXCEPT { @@ -526,7 +529,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference_wrapper cref(const _Tp& __t) _NOEXCEPT { @@ -534,7 +537,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference_wrapper cref(reference_wrapper<_Tp> __t) _NOEXCEPT { diff --git a/libcxx/include/functional b/libcxx/include/functional --- a/libcxx/include/functional +++ b/libcxx/include/functional @@ -213,7 +213,8 @@ template // deprecated in C++17 binary_negate not2(const Predicate& pred); -template unspecified not_fn(F&& f); // C++17 +template +constexpr unspecified not_fn(F&& f); // C++17, constexpr in C++20 template struct is_bind_expression; template struct is_placeholder; @@ -226,11 +227,12 @@ template - unspecified bind(Fn&&, BoundArgs&&...); + constexpr unspecified bind(Fn&&, BoundArgs&&...); // constexpr in C++20 template - unspecified bind(Fn&&, BoundArgs&&...); + constexpr unspecified bind(Fn&&, BoundArgs&&...); // constexpr in C++20 template + constexpr // constexpr in C++20 invoke_result_t invoke(F&& f, Args&&... args) // C++17 noexcept(is_nothrow_invocable_v); @@ -376,7 +378,8 @@ template const_mem_fun_ref_t mem_fun_ref(S (T::*f)() const); // deprecated in C++11, removed in C++17 template const_mem_fun1_ref_t mem_fun_ref(S (T::*f)(A) const); // deprecated in C++11, removed in C++17 -template unspecified mem_fn(R T::*); +template +constexpr unspecified mem_fn(R T::*); // constexpr in C++20 class bad_function_call : public exception @@ -1288,12 +1291,13 @@ type __f_; public: - _LIBCPP_INLINE_VISIBILITY __mem_fn(type __f) _NOEXCEPT : __f_(__f) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + __mem_fn(type __f) _NOEXCEPT : __f_(__f) {} #ifndef _LIBCPP_CXX03_LANG // invoke template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename __invoke_return::type operator() (_ArgTypes&&... __args) const { return _VSTD::__invoke(__f_, _VSTD::forward<_ArgTypes>(__args)...); @@ -1401,7 +1405,7 @@ }; template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __mem_fn<_Rp _Tp::*> mem_fn(_Rp _Tp::* __pm) _NOEXCEPT { @@ -2873,13 +2877,13 @@ !is_same::type, __bind>::value >::type> - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit __bind(_Gp&& __f, _BA&& ...__bound_args) : __f_(_VSTD::forward<_Gp>(__f)), __bound_args_(_VSTD::forward<_BA>(__bound_args)...) {} template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type operator()(_Args&& ...__args) { @@ -2888,7 +2892,7 @@ } template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename __bind_return >::type operator()(_Args&& ...__args) const { @@ -2918,13 +2922,13 @@ !is_same::type, __bind_r>::value >::type> - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit __bind_r(_Gp&& __f, _BA&& ...__bound_args) : base(_VSTD::forward<_Gp>(__f), _VSTD::forward<_BA>(__bound_args)...) {} template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < is_convertible >::type, @@ -2938,7 +2942,7 @@ } template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < is_convertible >::type, @@ -2956,7 +2960,7 @@ struct __is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {}; template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bind<_Fp, _BoundArgs...> bind(_Fp&& __f, _BoundArgs&&... __bound_args) { @@ -2965,7 +2969,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bind_r<_Rp, _Fp, _BoundArgs...> bind(_Fp&& __f, _BoundArgs&&... __bound_args) { @@ -2978,7 +2982,7 @@ #if _LIBCPP_STD_VER > 14 template -invoke_result_t<_Fn, _Args...> +_LIBCPP_CONSTEXPR_AFTER_CXX17 invoke_result_t<_Fn, _Args...> invoke(_Fn&& __f, _Args&&... __args) noexcept(is_nothrow_invocable_v<_Fn, _Args...>) { @@ -2993,21 +2997,21 @@ __not_fn_imp() = delete; template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 auto operator()(_Args&& ...__args) & noexcept(noexcept(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...))) -> decltype( !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...)) { return !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...); } template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 auto operator()(_Args&& ...__args) && noexcept(noexcept(!_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...))) -> decltype( !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...)) { return !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...); } template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 auto operator()(_Args&& ...__args) const& noexcept(noexcept(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...))) -> decltype( !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...)) @@ -3015,7 +3019,7 @@ template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 auto operator()(_Args&& ...__args) const&& noexcept(noexcept(!_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...))) -> decltype( !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...)) @@ -3024,17 +3028,17 @@ private: template , __not_fn_imp>::value>> - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit __not_fn_imp(_RawFunc&& __rf) : __fd(_VSTD::forward<_RawFunc>(__rf)) {} template - friend inline _LIBCPP_INLINE_VISIBILITY + friend inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __not_fn_imp> not_fn(_RawFunc&&); }; template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __not_fn_imp> not_fn(_RawFunc&& __fn) { return __not_fn_imp>(_VSTD::forward<_RawFunc>(__fn)); } @@ -3131,13 +3135,13 @@ template> class _LIBCPP_TYPE_VIS default_searcher { public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 default_searcher(_ForwardIterator __f, _ForwardIterator __l, _BinaryPredicate __p = _BinaryPredicate()) : __first_(__f), __last_(__l), __pred_(__p) {} template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_ForwardIterator2, _ForwardIterator2> operator () (_ForwardIterator2 __f, _ForwardIterator2 __l) const { diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -3584,7 +3584,7 @@ template > inline _LIBCPP_INLINE_VISIBILITY -auto +_LIBCPP_CONSTEXPR_AFTER_CXX17 auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) _LIBCPP_INVOKE_RETURN((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...)) @@ -3598,7 +3598,7 @@ template > inline _LIBCPP_INLINE_VISIBILITY -auto +_LIBCPP_CONSTEXPR_AFTER_CXX17 auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) _LIBCPP_INVOKE_RETURN((__a0.get().*__f)(_VSTD::forward<_Args>(__args)...)) @@ -3612,7 +3612,7 @@ template > inline _LIBCPP_INLINE_VISIBILITY -auto +_LIBCPP_CONSTEXPR_AFTER_CXX17 auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) _LIBCPP_INVOKE_RETURN(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...)) @@ -3628,7 +3628,7 @@ template > inline _LIBCPP_INLINE_VISIBILITY -auto +_LIBCPP_CONSTEXPR_AFTER_CXX17 auto __invoke(_Fp&& __f, _A0&& __a0) _LIBCPP_INVOKE_RETURN(_VSTD::forward<_A0>(__a0).*__f) @@ -3642,7 +3642,7 @@ template > inline _LIBCPP_INLINE_VISIBILITY -auto +_LIBCPP_CONSTEXPR_AFTER_CXX17 auto __invoke(_Fp&& __f, _A0&& __a0) _LIBCPP_INVOKE_RETURN(__a0.get().*__f) @@ -3656,7 +3656,7 @@ template > inline _LIBCPP_INLINE_VISIBILITY -auto +_LIBCPP_CONSTEXPR_AFTER_CXX17 auto __invoke(_Fp&& __f, _A0&& __a0) _LIBCPP_INVOKE_RETURN((*_VSTD::forward<_A0>(__a0)).*__f) @@ -3671,7 +3671,7 @@ template inline _LIBCPP_INLINE_VISIBILITY -auto +_LIBCPP_CONSTEXPR_AFTER_CXX17 auto __invoke(_Fp&& __f, _Args&& ...__args) _LIBCPP_INVOKE_RETURN(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...)) diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -46,8 +46,7 @@ __cpp_lib_complex_udls 201309L __cpp_lib_concepts 201806L __cpp_lib_constexpr_dynamic_alloc 201907L -__cpp_lib_constexpr_misc 201811L - +__cpp_lib_constexpr_functional 201907L __cpp_lib_constexpr_numeric 201911L __cpp_lib_constexpr_swap_algorithms 201806L __cpp_lib_constexpr_utility 201811L @@ -254,7 +253,7 @@ # endif // # define __cpp_lib_concepts 201806L # define __cpp_lib_constexpr_dynamic_alloc 201907L -// # define __cpp_lib_constexpr_misc 201811L +# define __cpp_lib_constexpr_functional 201907L # define __cpp_lib_constexpr_numeric 201911L // # define __cpp_lib_constexpr_swap_algorithms 201806L # define __cpp_lib_constexpr_utility 201811L diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp @@ -16,7 +16,6 @@ /* Constant Value __cpp_lib_array_constexpr 201603L [C++17] 201811L [C++2a] - __cpp_lib_constexpr_misc 201811L [C++2a] __cpp_lib_nonmember_container_access 201411L [C++17] __cpp_lib_to_array 201907L [C++2a] */ @@ -30,10 +29,6 @@ # error "__cpp_lib_array_constexpr should not be defined before c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifdef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should not be defined before c++17" # endif @@ -48,10 +43,6 @@ # error "__cpp_lib_array_constexpr should not be defined before c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifdef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should not be defined before c++17" # endif @@ -69,10 +60,6 @@ # error "__cpp_lib_array_constexpr should have the value 201603L in c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifndef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should be defined in c++17" # endif @@ -93,19 +80,6 @@ # error "__cpp_lib_array_constexpr should have the value 201811L in c++2a" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should be defined in c++2a" -# endif -# if __cpp_lib_constexpr_misc != 201811L -# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!" -# endif -# endif - # ifndef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should be defined in c++2a" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.pass.cpp @@ -16,7 +16,7 @@ /* Constant Value __cpp_lib_bind_front 201811L [C++2a] __cpp_lib_boyer_moore_searcher 201603L [C++17] - __cpp_lib_constexpr_misc 201811L [C++2a] + __cpp_lib_constexpr_functional 201907L [C++2a] __cpp_lib_invoke 201411L [C++17] __cpp_lib_not_fn 201603L [C++17] __cpp_lib_ranges 201811L [C++2a] @@ -38,8 +38,8 @@ # error "__cpp_lib_boyer_moore_searcher should not be defined before c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" +# ifdef __cpp_lib_constexpr_functional +# error "__cpp_lib_constexpr_functional should not be defined before c++2a" # endif # ifdef __cpp_lib_invoke @@ -72,8 +72,8 @@ # error "__cpp_lib_boyer_moore_searcher should not be defined before c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" +# ifdef __cpp_lib_constexpr_functional +# error "__cpp_lib_constexpr_functional should not be defined before c++2a" # endif # ifdef __cpp_lib_invoke @@ -121,8 +121,8 @@ # endif # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" +# ifdef __cpp_lib_constexpr_functional +# error "__cpp_lib_constexpr_functional should not be defined before c++2a" # endif # ifndef __cpp_lib_invoke @@ -185,17 +185,11 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should be defined in c++2a" -# endif -# if __cpp_lib_constexpr_misc != 201811L -# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_constexpr_functional +# error "__cpp_lib_constexpr_functional should be defined in c++2a" +# endif +# if __cpp_lib_constexpr_functional != 201907L +# error "__cpp_lib_constexpr_functional should have the value 201907L in c++2a" # endif # ifndef __cpp_lib_invoke diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp @@ -16,7 +16,6 @@ /* Constant Value __cpp_lib_array_constexpr 201603L [C++17] 201811L [C++2a] - __cpp_lib_constexpr_misc 201811L [C++2a] __cpp_lib_make_reverse_iterator 201402L [C++14] __cpp_lib_nonmember_container_access 201411L [C++17] __cpp_lib_null_iterators 201304L [C++14] @@ -32,10 +31,6 @@ # error "__cpp_lib_array_constexpr should not be defined before c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifdef __cpp_lib_make_reverse_iterator # error "__cpp_lib_make_reverse_iterator should not be defined before c++14" # endif @@ -58,10 +53,6 @@ # error "__cpp_lib_array_constexpr should not be defined before c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifndef __cpp_lib_make_reverse_iterator # error "__cpp_lib_make_reverse_iterator should be defined in c++14" # endif @@ -93,10 +84,6 @@ # error "__cpp_lib_array_constexpr should have the value 201603L in c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifndef __cpp_lib_make_reverse_iterator # error "__cpp_lib_make_reverse_iterator should be defined in c++17" # endif @@ -131,19 +118,6 @@ # error "__cpp_lib_array_constexpr should have the value 201811L in c++2a" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should be defined in c++2a" -# endif -# if __cpp_lib_constexpr_misc != 201811L -# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!" -# endif -# endif - # ifndef __cpp_lib_make_reverse_iterator # error "__cpp_lib_make_reverse_iterator should be defined in c++2a" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.pass.cpp @@ -13,10 +13,9 @@ // Test the feature test macros defined by -/* Constant Value - __cpp_lib_char8_t 201811L [C++2a] - __cpp_lib_constexpr_misc 201811L [C++2a] - __cpp_lib_string_view 201606L [C++17] +/* Constant Value + __cpp_lib_char8_t 201811L [C++2a] + __cpp_lib_string_view 201606L [C++17] */ #include @@ -28,10 +27,6 @@ # error "__cpp_lib_char8_t should not be defined before c++2a" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifdef __cpp_lib_string_view # error "__cpp_lib_string_view should not be defined before c++17" # endif @@ -42,10 +37,6 @@ # error "__cpp_lib_char8_t should not be defined before c++2a" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifdef __cpp_lib_string_view # error "__cpp_lib_string_view should not be defined before c++17" # endif @@ -56,10 +47,6 @@ # error "__cpp_lib_char8_t should not be defined before c++2a" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifndef __cpp_lib_string_view # error "__cpp_lib_string_view should be defined in c++17" # endif @@ -82,19 +69,6 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should be defined in c++2a" -# endif -# if __cpp_lib_constexpr_misc != 201811L -# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!" -# endif -# endif - # ifndef __cpp_lib_string_view # error "__cpp_lib_string_view should be defined in c++2a" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/tuple.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/tuple.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/tuple.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/tuple.version.pass.cpp @@ -15,7 +15,6 @@ /* Constant Value __cpp_lib_apply 201603L [C++17] - __cpp_lib_constexpr_misc 201811L [C++2a] __cpp_lib_make_from_tuple 201606L [C++17] __cpp_lib_tuple_element_t 201402L [C++14] __cpp_lib_tuples_by_type 201304L [C++14] @@ -30,10 +29,6 @@ # error "__cpp_lib_apply should not be defined before c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifdef __cpp_lib_make_from_tuple # error "__cpp_lib_make_from_tuple should not be defined before c++17" # endif @@ -52,10 +47,6 @@ # error "__cpp_lib_apply should not be defined before c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifdef __cpp_lib_make_from_tuple # error "__cpp_lib_make_from_tuple should not be defined before c++17" # endif @@ -83,10 +74,6 @@ # error "__cpp_lib_apply should have the value 201603L in c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifndef __cpp_lib_make_from_tuple # error "__cpp_lib_make_from_tuple should be defined in c++17" # endif @@ -117,19 +104,6 @@ # error "__cpp_lib_apply should have the value 201603L in c++2a" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should be defined in c++2a" -# endif -# if __cpp_lib_constexpr_misc != 201811L -# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!" -# endif -# endif - # ifndef __cpp_lib_make_from_tuple # error "__cpp_lib_make_from_tuple should be defined in c++2a" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp @@ -15,7 +15,6 @@ /* Constant Value __cpp_lib_as_const 201510L [C++17] - __cpp_lib_constexpr_misc 201811L [C++2a] __cpp_lib_constexpr_utility 201811L [C++2a] __cpp_lib_exchange_function 201304L [C++14] __cpp_lib_integer_sequence 201304L [C++14] @@ -32,10 +31,6 @@ # error "__cpp_lib_as_const should not be defined before c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifdef __cpp_lib_constexpr_utility # error "__cpp_lib_constexpr_utility should not be defined before c++2a" # endif @@ -62,10 +57,6 @@ # error "__cpp_lib_as_const should not be defined before c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifdef __cpp_lib_constexpr_utility # error "__cpp_lib_constexpr_utility should not be defined before c++2a" # endif @@ -104,10 +95,6 @@ # error "__cpp_lib_as_const should have the value 201510L in c++17" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" -# endif - # ifdef __cpp_lib_constexpr_utility # error "__cpp_lib_constexpr_utility should not be defined before c++2a" # endif @@ -155,19 +142,6 @@ # error "__cpp_lib_as_const should have the value 201510L in c++2a" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should be defined in c++2a" -# endif -# if __cpp_lib_constexpr_misc != 201811L -# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!" -# endif -# endif - # ifndef __cpp_lib_constexpr_utility # error "__cpp_lib_constexpr_utility should be defined in c++2a" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp @@ -41,7 +41,7 @@ __cpp_lib_complex_udls 201309L [C++14] __cpp_lib_concepts 201806L [C++2a] __cpp_lib_constexpr_dynamic_alloc 201907L [C++2a] - __cpp_lib_constexpr_misc 201811L [C++2a] + __cpp_lib_constexpr_functional 201907L [C++2a] __cpp_lib_constexpr_numeric 201911L [C++2a] __cpp_lib_constexpr_swap_algorithms 201806L [C++2a] __cpp_lib_constexpr_utility 201811L [C++2a] @@ -224,8 +224,8 @@ # error "__cpp_lib_constexpr_dynamic_alloc should not be defined before c++2a" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" +# ifdef __cpp_lib_constexpr_functional +# error "__cpp_lib_constexpr_functional should not be defined before c++2a" # endif # ifdef __cpp_lib_constexpr_numeric @@ -620,8 +620,8 @@ # error "__cpp_lib_constexpr_dynamic_alloc should not be defined before c++2a" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" +# ifdef __cpp_lib_constexpr_functional +# error "__cpp_lib_constexpr_functional should not be defined before c++2a" # endif # ifdef __cpp_lib_constexpr_numeric @@ -1130,8 +1130,8 @@ # error "__cpp_lib_constexpr_dynamic_alloc should not be defined before c++2a" # endif -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined before c++2a" +# ifdef __cpp_lib_constexpr_functional +# error "__cpp_lib_constexpr_functional should not be defined before c++2a" # endif # ifdef __cpp_lib_constexpr_numeric @@ -1904,17 +1904,11 @@ # error "__cpp_lib_constexpr_dynamic_alloc should have the value 201907L in c++2a" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should be defined in c++2a" -# endif -# if __cpp_lib_constexpr_misc != 201811L -# error "__cpp_lib_constexpr_misc should have the value 201811L in c++2a" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_constexpr_misc -# error "__cpp_lib_constexpr_misc should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_constexpr_functional +# error "__cpp_lib_constexpr_functional should be defined in c++2a" +# endif +# if __cpp_lib_constexpr_functional != 201907L +# error "__cpp_lib_constexpr_functional should have the value 201907L in c++2a" # endif # ifndef __cpp_lib_constexpr_numeric diff --git a/libcxx/test/std/utilities/function.objects/func.invoke/invoke_constexpr.pass.cpp b/libcxx/test/std/utilities/function.objects/func.invoke/invoke_constexpr.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/function.objects/func.invoke/invoke_constexpr.pass.cpp @@ -0,0 +1,279 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template +// constexpr // constexpr in C++20 +// invoke_result_t invoke(F&& f, Args&&... args) +// noexcept(is_nothrow_invocable_v<_Fn, _Args...>); + +/// C++14 [func.def] 20.9.0 +/// (1) The following definitions apply to this Clause: +/// (2) A call signature is the name of a return type followed by a parenthesized +/// comma-separated list of zero or more argument types. +/// (3) A callable type is a function object type (20.9) or a pointer to member. +/// (4) A callable object is an object of a callable type. +/// (5) A call wrapper type is a type that holds a callable object and supports +/// a call operation that forwards to that object. +/// (6) A call wrapper is an object of a call wrapper type. +/// (7) A target object is the callable object held by a call wrapper. + +/// C++14 [func.require] 20.9.1 +/// +/// Define INVOKE (f, t1, t2, ..., tN) as follows: +/// (1.1) - (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of +/// type T or a reference to an object of type T or a reference to an object of a type derived from T; +/// (1.2) - ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of +/// the types described in the previous item; +/// (1.3) - t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a +/// reference to an object of type T or a reference to an object of a type derived from T; +/// (1.4) - (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types +/// described in the previous item; +/// (1.5) - f(t1, t2, ..., tN) in all other cases. + +#include +#include +#include // for std::move +#include + +#include "test_macros.h" + +struct NonCopyable { + constexpr NonCopyable() {} +private: + NonCopyable(NonCopyable const&) = delete; + NonCopyable& operator=(NonCopyable const&) = delete; +}; + +struct TestClass { + constexpr explicit TestClass(int x) : data(x) {} + + constexpr int& operator()(NonCopyable&&) & { return data; } + constexpr int const& operator()(NonCopyable&&) const & { return data; } + + constexpr int&& operator()(NonCopyable&&) && { return std::move(data); } + constexpr int const&& operator()(NonCopyable&&) const && { return std::move(data); } + + int data; +private: + TestClass(TestClass const&) = delete; + TestClass& operator=(TestClass const&) = delete; +}; + +struct DerivedFromTestClass : public TestClass { + constexpr explicit DerivedFromTestClass(int x) : TestClass(x) {} +}; + +static constexpr int data = 42; +constexpr const int& foo(NonCopyable&&) { + return data; +} + +template +constexpr void test_b12(Functor&& f) { + // Create the callable object. + typedef Signature TestClass::*ClassFunc; + ClassFunc func_ptr = &TestClass::operator(); + + // Create the dummy arg. + NonCopyable arg; + + // Check that the deduced return type of invoke is what is expected. + typedef decltype( + std::invoke(func_ptr, std::forward(f), std::move(arg)) + ) DeducedReturnType; + static_assert((std::is_same::value), ""); + + // Check that result_of_t matches Expect. + typedef typename std::result_of::type + ResultOfReturnType; + static_assert((std::is_same::value), ""); + + // Run invoke and check the return value. + DeducedReturnType ret = + std::invoke(func_ptr, std::forward(f), std::move(arg)); + assert(ret == 42); +} + +template +constexpr void test_b34(Functor&& f) { + // Create the callable object. + typedef int TestClass::*ClassFunc; + ClassFunc func_ptr = &TestClass::data; + + // Check that the deduced return type of invoke is what is expected. + typedef decltype( + std::invoke(func_ptr, std::forward(f)) + ) DeducedReturnType; + static_assert((std::is_same::value), ""); + + // Check that result_of_t matches Expect. + typedef typename std::result_of::type + ResultOfReturnType; + static_assert((std::is_same::value), ""); + + // Run invoke and check the return value. + DeducedReturnType ret = + std::invoke(func_ptr, std::forward(f)); + assert(ret == 42); +} + +template +constexpr void test_b5(Functor&& f) { + NonCopyable arg; + + // Check that the deduced return type of invoke is what is expected. + typedef decltype( + std::invoke(std::forward(f), std::move(arg)) + ) DeducedReturnType; + static_assert((std::is_same::value), ""); + + // Check that result_of_t matches Expect. + typedef typename std::result_of::type + ResultOfReturnType; + static_assert((std::is_same::value), ""); + + // Run invoke and check the return value. + DeducedReturnType ret = std::invoke(std::forward(f), std::move(arg)); + assert(ret == 42); +} + +constexpr bool bullet_one_two_tests() { + { + TestClass cl(42); + test_b12(cl); + test_b12(cl); + + test_b12(std::move(cl)); + test_b12(std::move(cl)); + } + { + DerivedFromTestClass cl(42); + test_b12(cl); + test_b12(cl); + + test_b12(std::move(cl)); + test_b12(std::move(cl)); + } + { + TestClass cl_obj(42); + std::reference_wrapper cl(cl_obj); + test_b12(cl); + test_b12(cl); + + test_b12(std::move(cl)); + test_b12(std::move(cl)); + } + { + DerivedFromTestClass cl_obj(42); + std::reference_wrapper cl(cl_obj); + test_b12(cl); + test_b12(cl); + + test_b12(std::move(cl)); + test_b12(std::move(cl)); + } + { + TestClass cl_obj(42); + TestClass *cl = &cl_obj; + test_b12(cl); + test_b12(cl); + } + { + DerivedFromTestClass cl_obj(42); + DerivedFromTestClass *cl = &cl_obj; + test_b12(cl); + test_b12(cl); + } + return true; +} + +constexpr bool bullet_three_four_tests() { + { + typedef TestClass Fn; + Fn cl(42); + test_b34(cl); + test_b34(static_cast(cl)); + + test_b34(static_cast(cl)); + test_b34(static_cast(cl)); + } + { + typedef DerivedFromTestClass Fn; + Fn cl(42); + test_b34(cl); + test_b34(static_cast(cl)); + + test_b34(static_cast(cl)); + test_b34(static_cast(cl)); + } + { + typedef TestClass Fn; + Fn cl(42); + test_b34(std::reference_wrapper(cl)); + test_b34(std::reference_wrapper(cl)); + } + { + typedef DerivedFromTestClass Fn; + Fn cl(42); + test_b34(std::reference_wrapper(cl)); + test_b34(std::reference_wrapper(cl)); + } + { + typedef TestClass Fn; + Fn cl_obj(42); + Fn* cl = &cl_obj; + test_b34(cl); + test_b34(static_cast(cl)); + } + { + typedef DerivedFromTestClass Fn; + Fn cl_obj(42); + Fn* cl = &cl_obj; + test_b34(cl); + test_b34(static_cast(cl)); + } + return true; +} + +constexpr bool bullet_five_tests() { + using FooType = const int&(NonCopyable&&); + { + FooType& fn = foo; + test_b5(fn); + } + { + FooType* fn = foo; + test_b5(fn); + } + { + typedef TestClass Fn; + Fn cl(42); + test_b5(cl); + test_b5(static_cast(cl)); + + test_b5(static_cast(cl)); + test_b5(static_cast(cl)); + } + return true; +} + +int main(int, char**) { + bullet_one_two_tests(); + bullet_three_four_tests(); + bullet_five_tests(); + + static_assert(bullet_one_two_tests()); + static_assert(bullet_three_four_tests()); + static_assert(bullet_five_tests()); + + return 0; +} diff --git a/libcxx/test/std/utilities/function.objects/func.memfn/member_data.pass.cpp b/libcxx/test/std/utilities/function.objects/func.memfn/member_data.pass.cpp --- a/libcxx/test/std/utilities/function.objects/func.memfn/member_data.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.memfn/member_data.pass.cpp @@ -21,7 +21,7 @@ }; template -void +TEST_CONSTEXPR_CXX20 bool test(F f) { { @@ -36,11 +36,16 @@ const F& cf = f; assert(cf(ap) == f(ap)); } + return true; } int main(int, char**) { test(std::mem_fn(&A::data_)); - return 0; +#if TEST_STD_VER >= 20 + static_assert(test(std::mem_fn(&A::data_))); +#endif + + return 0; } diff --git a/libcxx/test/std/utilities/function.objects/func.memfn/member_function.pass.cpp b/libcxx/test/std/utilities/function.objects/func.memfn/member_function.pass.cpp --- a/libcxx/test/std/utilities/function.objects/func.memfn/member_function.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.memfn/member_function.pass.cpp @@ -18,13 +18,13 @@ struct A { - char test0() {return 'a';} - char test1(int) {return 'b';} - char test2(int, double) {return 'c';} + TEST_CONSTEXPR_CXX14 char test0() {return 'a';} + TEST_CONSTEXPR_CXX14 char test1(int) {return 'b';} + TEST_CONSTEXPR_CXX14 char test2(int, double) {return 'c';} }; template -void +TEST_CONSTEXPR_CXX20 bool test0(F f) { { @@ -35,10 +35,11 @@ const F& cf = f; assert(cf(ap) == 'a'); } + return true; } template -void +TEST_CONSTEXPR_CXX20 bool test1(F f) { { @@ -49,10 +50,11 @@ const F& cf = f; assert(cf(ap, 2) == 'b'); } + return true; } template -void +TEST_CONSTEXPR_CXX20 bool test2(F f) { { @@ -63,6 +65,7 @@ const F& cf = f; assert(cf(ap, 2, 3.5) == 'c'); } + return true; } int main(int, char**) @@ -74,5 +77,11 @@ static_assert((noexcept(std::mem_fn(&A::test0))), ""); // LWG#2489 #endif - return 0; +#if TEST_STD_VER >= 20 + static_assert(test0(std::mem_fn(&A::test0))); + static_assert(test1(std::mem_fn(&A::test1))); + static_assert(test2(std::mem_fn(&A::test2))); +#endif + + return 0; } diff --git a/libcxx/test/std/utilities/function.objects/func.memfn/member_function_const.pass.cpp b/libcxx/test/std/utilities/function.objects/func.memfn/member_function_const.pass.cpp --- a/libcxx/test/std/utilities/function.objects/func.memfn/member_function_const.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.memfn/member_function_const.pass.cpp @@ -18,13 +18,13 @@ struct A { - char test0() const {return 'a';} - char test1(int) const {return 'b';} - char test2(int, double) const {return 'c';} + TEST_CONSTEXPR char test0() const {return 'a';} + TEST_CONSTEXPR char test1(int) const {return 'b';} + TEST_CONSTEXPR char test2(int, double) const {return 'c';} }; template -void +TEST_CONSTEXPR_CXX20 bool test0(F f) { { @@ -37,10 +37,11 @@ const F& cf = f; assert(cf(ap) == 'a'); } + return true; } template -void +TEST_CONSTEXPR_CXX20 bool test1(F f) { { @@ -53,10 +54,11 @@ const F& cf = f; assert(cf(ap, 2) == 'b'); } + return true; } template -void +TEST_CONSTEXPR_CXX20 bool test2(F f) { { @@ -69,6 +71,7 @@ const F& cf = f; assert(cf(ap, 2, 3.5) == 'c'); } + return true; } int main(int, char**) @@ -77,5 +80,11 @@ test1(std::mem_fn(&A::test1)); test2(std::mem_fn(&A::test2)); - return 0; +#if TEST_STD_VER >= 20 + static_assert(test0(std::mem_fn(&A::test0))); + static_assert(test1(std::mem_fn(&A::test1))); + static_assert(test2(std::mem_fn(&A::test2))); +#endif + + return 0; } diff --git a/libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp b/libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp --- a/libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp @@ -23,50 +23,50 @@ // CALLABLE TEST TYPES /////////////////////////////////////////////////////////////////////////////// -bool returns_true() { return true; } +constexpr bool returns_true() { return true; } template struct MoveOnlyCallable { MoveOnlyCallable(MoveOnlyCallable const&) = delete; - MoveOnlyCallable(MoveOnlyCallable&& other) + constexpr MoveOnlyCallable(MoveOnlyCallable&& other) : value(other.value) { other.value = !other.value; } template - Ret operator()(Args&&...) { return Ret{value}; } + constexpr Ret operator()(Args&&...) { return Ret{value}; } - explicit MoveOnlyCallable(bool x) : value(x) {} + constexpr explicit MoveOnlyCallable(bool x) : value(x) {} Ret value; }; template struct CopyCallable { - CopyCallable(CopyCallable const& other) + constexpr CopyCallable(CopyCallable const& other) : value(other.value) {} - CopyCallable(CopyCallable&& other) + constexpr CopyCallable(CopyCallable&& other) : value(other.value) { other.value = !other.value; } template - Ret operator()(Args&&...) { return Ret{value}; } + constexpr Ret operator()(Args&&...) { return Ret{value}; } - explicit CopyCallable(bool x) : value(x) {} + constexpr explicit CopyCallable(bool x) : value(x) {} Ret value; }; template struct ConstCallable { - ConstCallable(ConstCallable const& other) + constexpr ConstCallable(ConstCallable const& other) : value(other.value) {} - ConstCallable(ConstCallable&& other) + constexpr ConstCallable(ConstCallable&& other) : value(other.value) { other.value = !other.value; } template - Ret operator()(Args&&...) const { return Ret{value}; } + constexpr Ret operator()(Args&&...) const { return Ret{value}; } - explicit ConstCallable(bool x) : value(x) {} + constexpr explicit ConstCallable(bool x) : value(x) {} Ret value; }; @@ -74,51 +74,51 @@ template struct NoExceptCallable { - NoExceptCallable(NoExceptCallable const& other) + constexpr NoExceptCallable(NoExceptCallable const& other) : value(other.value) {} template - Ret operator()(Args&&...) noexcept { return Ret{value}; } + constexpr Ret operator()(Args&&...) noexcept { return Ret{value}; } template - Ret operator()(Args&&...) const noexcept { return Ret{value}; } + constexpr Ret operator()(Args&&...) const noexcept { return Ret{value}; } - explicit NoExceptCallable(bool x) : value(x) {} + constexpr explicit NoExceptCallable(bool x) : value(x) {} Ret value; }; struct CopyAssignableWrapper { - CopyAssignableWrapper(CopyAssignableWrapper const&) = default; - CopyAssignableWrapper(CopyAssignableWrapper&&) = default; - CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default; - CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default; + constexpr CopyAssignableWrapper(CopyAssignableWrapper const&) = default; + constexpr CopyAssignableWrapper(CopyAssignableWrapper&&) = default; + constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default; + constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default; template - bool operator()(Args&&...) { return value; } + constexpr bool operator()(Args&&...) { return value; } - explicit CopyAssignableWrapper(bool x) : value(x) {} + constexpr explicit CopyAssignableWrapper(bool x) : value(x) {} bool value; }; struct MoveAssignableWrapper { - MoveAssignableWrapper(MoveAssignableWrapper const&) = delete; - MoveAssignableWrapper(MoveAssignableWrapper&&) = default; - MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete; - MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default; + constexpr MoveAssignableWrapper(MoveAssignableWrapper const&) = delete; + constexpr MoveAssignableWrapper(MoveAssignableWrapper&&) = default; + constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete; + constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default; template - bool operator()(Args&&...) { return value; } + constexpr bool operator()(Args&&...) { return value; } - explicit MoveAssignableWrapper(bool x) : value(x) {} + constexpr explicit MoveAssignableWrapper(bool x) : value(x) {} bool value; }; struct MemFunCallable { - explicit MemFunCallable(bool x) : value(x) {} + constexpr explicit MemFunCallable(bool x) : value(x) {} - bool return_value() const { return value; } - bool return_value_nc() { return value; } + constexpr bool return_value() const { return value; } + constexpr bool return_value_nc() { return value; } bool value; }; @@ -135,59 +135,60 @@ } struct ForwardingCallObject { + struct State { + CallType last_call_type = CT_None; + TypeID const& (*last_call_args)() = nullptr; + + template + constexpr void set_call(CallType type) { + assert(last_call_type == CT_None); + assert(last_call_args == nullptr); + last_call_type = type; + last_call_args = &makeArgumentID; + } + + template + constexpr bool check_call(CallType type) { + bool result = + last_call_type == type + && last_call_args + && *last_call_args == &makeArgumentID; + last_call_type = CT_None; + last_call_args = nullptr; + return result; + } + }; + + State *st_; + + explicit constexpr ForwardingCallObject(State& st) : st_(&st) {} template - bool operator()(Args&&...) & { - set_call(CT_NonConst | CT_LValue); + constexpr bool operator()(Args&&...) & { + st_->set_call(CT_NonConst | CT_LValue); return true; } template - bool operator()(Args&&...) const & { - set_call(CT_Const | CT_LValue); + constexpr bool operator()(Args&&...) const & { + st_->set_call(CT_Const | CT_LValue); return true; } // Don't allow the call operator to be invoked as an rvalue. template - bool operator()(Args&&...) && { - set_call(CT_NonConst | CT_RValue); + constexpr bool operator()(Args&&...) && { + st_->set_call(CT_NonConst | CT_RValue); return true; } template - bool operator()(Args&&...) const && { - set_call(CT_Const | CT_RValue); + constexpr bool operator()(Args&&...) const && { + st_->set_call(CT_Const | CT_RValue); return true; } - - template - static void set_call(CallType type) { - assert(last_call_type == CT_None); - assert(last_call_args == nullptr); - last_call_type = type; - last_call_args = &makeArgumentID(); - } - - template - static bool check_call(CallType type) { - bool result = - last_call_type == type - && last_call_args - && *last_call_args == makeArgumentID(); - last_call_type = CT_None; - last_call_args = nullptr; - return result; - } - - static CallType last_call_type; - static TypeID const* last_call_args; }; -CallType ForwardingCallObject::last_call_type = CT_None; -TypeID const* ForwardingCallObject::last_call_args = nullptr; - - /////////////////////////////////////////////////////////////////////////////// // BOOL TEST TYPES @@ -209,7 +210,7 @@ friend struct CopyCallable; friend struct NoExceptCallable; - explicit EvilBool(bool x) : value(x) {} + constexpr explicit EvilBool(bool x) : value(x) {} EvilBool& operator=(EvilBool const& other) = default; public: @@ -222,14 +223,14 @@ ExplicitBool(ExplicitBool const&) = default; ExplicitBool(ExplicitBool&&) = default; - explicit operator bool() const { return value; } + constexpr explicit operator bool() const { return value; } private: friend struct MoveOnlyCallable; friend struct CopyCallable; - explicit ExplicitBool(bool x) : value(x) {} - ExplicitBool& operator=(bool x) { + constexpr explicit ExplicitBool(bool x) : value(x) {} + constexpr ExplicitBool& operator=(bool x) { value = x; return *this; } @@ -243,7 +244,7 @@ NoExceptEvilBool(NoExceptEvilBool&&) = default; NoExceptEvilBool& operator=(NoExceptEvilBool const& other) = default; - explicit NoExceptEvilBool(bool x) : value(x) {} + constexpr explicit NoExceptEvilBool(bool x) : value(x) {} friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept { return NoExceptEvilBool{!other.value}; @@ -254,7 +255,8 @@ -void constructor_tests() +TEST_CONSTEXPR_CXX20 +bool constructor_tests() { { using T = MoveOnlyCallable; @@ -334,6 +336,7 @@ assert(ret() == true); #endif // _LIBCPP_VERSION } + return true; } void return_type_tests() @@ -368,7 +371,8 @@ // Other tests only test using objects with call operators. Test various // other callable types here. -void other_callable_types_test() +TEST_CONSTEXPR_CXX20 +bool other_callable_types_test() { { // test with function pointer auto ret = std::not_fn(returns_true); @@ -407,6 +411,7 @@ assert(ret(&mt) == false); assert(ret(&mf) == true); } + return true; } void throws_in_constructor_test() @@ -438,7 +443,8 @@ #endif } -void call_operator_sfinae_test() { +TEST_CONSTEXPR_CXX20 +bool call_operator_sfinae_test() { { // wrong number of arguments using T = decltype(std::not_fn(returns_true)); static_assert(std::is_invocable::value, ""); // callable only with no args @@ -462,94 +468,100 @@ static_assert(std::is_invocable::value, ""); static_assert(!std::is_invocable::value, ""); } + return true; } -void call_operator_forwarding_test() +TEST_CONSTEXPR_CXX20 +bool call_operator_forwarding_test() { using Fn = ForwardingCallObject; - auto obj = std::not_fn(Fn{}); + Fn::State st; + auto obj = std::not_fn(Fn{st}); const auto& c_obj = obj; { // test zero args obj(); - assert(Fn::check_call<>(CT_NonConst | CT_LValue)); + assert(st.check_call<>(CT_NonConst | CT_LValue)); std::move(obj)(); - assert(Fn::check_call<>(CT_NonConst | CT_RValue)); + assert(st.check_call<>(CT_NonConst | CT_RValue)); c_obj(); - assert(Fn::check_call<>(CT_Const | CT_LValue)); + assert(st.check_call<>(CT_Const | CT_LValue)); std::move(c_obj)(); - assert(Fn::check_call<>(CT_Const | CT_RValue)); + assert(st.check_call<>(CT_Const | CT_RValue)); } { // test value categories int x = 42; const int cx = 42; obj(x); - assert(Fn::check_call(CT_NonConst | CT_LValue)); + assert(st.check_call(CT_NonConst | CT_LValue)); obj(cx); - assert(Fn::check_call(CT_NonConst | CT_LValue)); + assert(st.check_call(CT_NonConst | CT_LValue)); obj(std::move(x)); - assert(Fn::check_call(CT_NonConst | CT_LValue)); + assert(st.check_call(CT_NonConst | CT_LValue)); obj(std::move(cx)); - assert(Fn::check_call(CT_NonConst | CT_LValue)); + assert(st.check_call(CT_NonConst | CT_LValue)); obj(42); - assert(Fn::check_call(CT_NonConst | CT_LValue)); + assert(st.check_call(CT_NonConst | CT_LValue)); } { // test value categories - rvalue int x = 42; const int cx = 42; std::move(obj)(x); - assert(Fn::check_call(CT_NonConst | CT_RValue)); + assert(st.check_call(CT_NonConst | CT_RValue)); std::move(obj)(cx); - assert(Fn::check_call(CT_NonConst | CT_RValue)); + assert(st.check_call(CT_NonConst | CT_RValue)); std::move(obj)(std::move(x)); - assert(Fn::check_call(CT_NonConst | CT_RValue)); + assert(st.check_call(CT_NonConst | CT_RValue)); std::move(obj)(std::move(cx)); - assert(Fn::check_call(CT_NonConst | CT_RValue)); + assert(st.check_call(CT_NonConst | CT_RValue)); std::move(obj)(42); - assert(Fn::check_call(CT_NonConst | CT_RValue)); + assert(st.check_call(CT_NonConst | CT_RValue)); } { // test value categories - const call int x = 42; const int cx = 42; c_obj(x); - assert(Fn::check_call(CT_Const | CT_LValue)); + assert(st.check_call(CT_Const | CT_LValue)); c_obj(cx); - assert(Fn::check_call(CT_Const | CT_LValue)); + assert(st.check_call(CT_Const | CT_LValue)); c_obj(std::move(x)); - assert(Fn::check_call(CT_Const | CT_LValue)); + assert(st.check_call(CT_Const | CT_LValue)); c_obj(std::move(cx)); - assert(Fn::check_call(CT_Const | CT_LValue)); + assert(st.check_call(CT_Const | CT_LValue)); c_obj(42); - assert(Fn::check_call(CT_Const | CT_LValue)); + assert(st.check_call(CT_Const | CT_LValue)); } { // test value categories - const call rvalue int x = 42; const int cx = 42; std::move(c_obj)(x); - assert(Fn::check_call(CT_Const | CT_RValue)); + assert(st.check_call(CT_Const | CT_RValue)); std::move(c_obj)(cx); - assert(Fn::check_call(CT_Const | CT_RValue)); + assert(st.check_call(CT_Const | CT_RValue)); std::move(c_obj)(std::move(x)); - assert(Fn::check_call(CT_Const | CT_RValue)); + assert(st.check_call(CT_Const | CT_RValue)); std::move(c_obj)(std::move(cx)); - assert(Fn::check_call(CT_Const | CT_RValue)); + assert(st.check_call(CT_Const | CT_RValue)); std::move(c_obj)(42); - assert(Fn::check_call(CT_Const | CT_RValue)); + assert(st.check_call(CT_Const | CT_RValue)); } { // test multi arg + using String = const char *; const double y = 3.14; - std::string s = "abc"; - obj(42, std::move(y), s, std::string{"foo"}); - Fn::check_call(CT_NonConst | CT_LValue); - std::move(obj)(42, std::move(y), s, std::string{"foo"}); - Fn::check_call(CT_NonConst | CT_RValue); - c_obj(42, std::move(y), s, std::string{"foo"}); - Fn::check_call(CT_Const | CT_LValue); - std::move(c_obj)(42, std::move(y), s, std::string{"foo"}); - Fn::check_call(CT_Const | CT_RValue); + String s = "abc"; + obj(42, std::move(y), s, String{"foo"}); + assert((st.check_call(CT_NonConst | CT_LValue))); + std::move(obj)(42, std::move(y), s, String{"foo"}); + assert((st.check_call(CT_NonConst | CT_RValue))); + c_obj(42, std::move(y), s, String{"foo"}); + assert((st.check_call(CT_Const | CT_LValue))); + std::move(c_obj)(42, std::move(y), s, String{"foo"}); + assert((st.check_call(CT_Const | CT_RValue))); } + return true; } -void call_operator_noexcept_test() +TEST_CONSTEXPR_CXX20 +bool call_operator_noexcept_test() { { using T = ConstCallable; @@ -587,19 +599,22 @@ auto const& cret = ret; static_assert(!noexcept(cret()), "call should not be noexcept"); } + return true; } -void test_lwg2767() { +TEST_CONSTEXPR_CXX20 +bool test_lwg2767() { // See https://cplusplus.github.io/LWG/lwg-defects.html#2767 struct Abstract { virtual void f() const = 0; }; struct Derived : public Abstract { void f() const {} }; - struct F { bool operator()(Abstract&&) { return false; } }; + struct F { constexpr bool operator()(Abstract&&) { return false; } }; { Derived d; Abstract &a = d; bool b = std::not_fn(F{})(std::move(a)); assert(b); } + return true; } int main(int, char**) @@ -613,5 +628,14 @@ call_operator_noexcept_test(); test_lwg2767(); - return 0; +#if TEST_STD_VER >= 20 + static_assert(constructor_tests()); + static_assert(other_callable_types_test()); + static_assert(call_operator_sfinae_test()); // somewhat of an extension + static_assert(call_operator_forwarding_test()); + static_assert(call_operator_noexcept_test()); + static_assert(test_lwg2767()); +#endif + + return 0; } diff --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.default/default.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.default/default.pass.cpp --- a/libcxx/test/std/utilities/function.objects/func.search/func.search.default/default.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.default/default.pass.cpp @@ -39,14 +39,15 @@ #include "test_iterators.h" template +TEST_CONSTEXPR_CXX20 void do_search(Iter1 b1, Iter1 e1, Iter2 b2, Iter2 e2, Iter1 result) { std::default_searcher s{b2, e2}; assert(result == std::search(b1, e1, s)); } template -void -test() +TEST_CONSTEXPR_CXX20 +bool test() { int ia[] = {0, 1, 2, 3, 4, 5}; const unsigned sa = sizeof(ia)/sizeof(ia[0]); @@ -81,6 +82,8 @@ int ik[] = {0, 0, 0, 0, 1, 1, 1, 1, 0, 0}; const unsigned sk = sizeof(ik)/sizeof(ik[0]); do_search(Iter1(ij), Iter1(ij+sj), Iter2(ik), Iter2(ik+sk), Iter1(ij+6)); + + return true; } int main(int, char**) { @@ -94,5 +97,17 @@ test, bidirectional_iterator >(); test, random_access_iterator >(); - return 0; +#if TEST_STD_VER >= 20 + static_assert(test, forward_iterator>()); + static_assert(test, bidirectional_iterator>()); + static_assert(test, random_access_iterator>()); + static_assert(test, forward_iterator>()); + static_assert(test, bidirectional_iterator>()); + static_assert(test, random_access_iterator>()); + static_assert(test, forward_iterator>()); + static_assert(test, bidirectional_iterator>()); + static_assert(test, random_access_iterator>()); +#endif + + return 0; } diff --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.default/default.pred.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.default/default.pred.pass.cpp --- a/libcxx/test/std/utilities/function.objects/func.search/func.search.default/default.pred.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.default/default.pred.pass.cpp @@ -40,54 +40,59 @@ struct count_equal { - static unsigned count; + unsigned *count; + template - bool operator()(const T& x, const T& y) const - {++count; return x == y;} + TEST_CONSTEXPR_CXX14 bool operator()(const T& x, const T& y) const + {++*count; return x == y;} }; -unsigned count_equal::count = 0; - template -void do_search(Iter1 b1, Iter1 e1, Iter2 b2, Iter2 e2, Iter1 result, unsigned max_count) { - std::default_searcher s{b2, e2}; - count_equal::count = 0; +TEST_CONSTEXPR_CXX20 +void do_search(Iter1 b1, Iter1 e1, Iter2 b2, Iter2 e2, Iter1 result) { + unsigned count = 0; + std::default_searcher s{b2, e2, count_equal{&count}}; assert(result == std::search(b1, e1, s)); - assert(count_equal::count <= max_count); + auto d1 = std::distance(b1, e1); + auto d2 = std::distance(b2, e2); + assert((count >= 1) || (d2 == 0) || (d1 < d2)); + assert((d1 < d2) || count <= d1 * (d1 - d2 + 1)); } template -void -test() +TEST_CONSTEXPR_CXX20 +bool test() { int ia[] = {0, 1, 2, 3, 4, 5}; const unsigned sa = sizeof(ia)/sizeof(ia[0]); - do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia), Iter1(ia), 0); - do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia+1), Iter1(ia), sa); - do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+1), Iter2(ia+2), Iter1(ia+1), sa); - do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+2), Iter2(ia+2), Iter1(ia), 0); - do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+2), Iter2(ia+3), Iter1(ia+2), sa); - do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+2), Iter2(ia+3), Iter1(ia+2), sa); - do_search(Iter1(ia), Iter1(ia), Iter2(ia+2), Iter2(ia+3), Iter1(ia), 0); - do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+sa-1), Iter2(ia+sa), Iter1(ia+sa-1), sa); - do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+sa-3), Iter2(ia+sa), Iter1(ia+sa-3), 3*sa); - do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia+sa), Iter1(ia), sa*sa); - do_search(Iter1(ia), Iter1(ia+sa-1), Iter2(ia), Iter2(ia+sa), Iter1(ia+sa-1), (sa-1)*sa); - do_search(Iter1(ia), Iter1(ia+1), Iter2(ia), Iter2(ia+sa), Iter1(ia+1), sa); + do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia), Iter1(ia)); + do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia+1), Iter1(ia)); + do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+1), Iter2(ia+2), Iter1(ia+1)); + do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+2), Iter2(ia+2), Iter1(ia)); + do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+2), Iter2(ia+3), Iter1(ia+2)); + do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+2), Iter2(ia+3), Iter1(ia+2)); + do_search(Iter1(ia), Iter1(ia), Iter2(ia+2), Iter2(ia+3), Iter1(ia)); + do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+sa-1), Iter2(ia+sa), Iter1(ia+sa-1)); + do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia+sa-3), Iter2(ia+sa), Iter1(ia+sa-3)); + do_search(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia+sa), Iter1(ia)); + do_search(Iter1(ia), Iter1(ia+sa-1), Iter2(ia), Iter2(ia+sa), Iter1(ia+sa-1)); + do_search(Iter1(ia), Iter1(ia+1), Iter2(ia), Iter2(ia+sa), Iter1(ia+1)); int ib[] = {0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4}; const unsigned sb = sizeof(ib)/sizeof(ib[0]); int ic[] = {1}; - do_search(Iter1(ib), Iter1(ib+sb), Iter2(ic), Iter2(ic+1), Iter1(ib+1), sb); + do_search(Iter1(ib), Iter1(ib+sb), Iter2(ic), Iter2(ic+1), Iter1(ib+1)); int id[] = {1, 2}; - do_search(Iter1(ib), Iter1(ib+sb), Iter2(id), Iter2(id+2), Iter1(ib+1), sb*2); + do_search(Iter1(ib), Iter1(ib+sb), Iter2(id), Iter2(id+2), Iter1(ib+1)); int ie[] = {1, 2, 3}; - do_search(Iter1(ib), Iter1(ib+sb), Iter2(ie), Iter2(ie+3), Iter1(ib+4), sb*3); + do_search(Iter1(ib), Iter1(ib+sb), Iter2(ie), Iter2(ie+3), Iter1(ib+4)); int ig[] = {1, 2, 3, 4}; - do_search(Iter1(ib), Iter1(ib+sb), Iter2(ig), Iter2(ig+4), Iter1(ib+8), sb*4); + do_search(Iter1(ib), Iter1(ib+sb), Iter2(ig), Iter2(ig+4), Iter1(ib+8)); int ih[] = {0, 1, 1, 1, 1, 2, 3, 0, 1, 2, 3, 4}; const unsigned sh = sizeof(ih)/sizeof(ih[0]); int ii[] = {1, 1, 2}; - do_search(Iter1(ih), Iter1(ih+sh), Iter2(ii), Iter2(ii+3), Iter1(ih+3), sh*3); + do_search(Iter1(ih), Iter1(ih+sh), Iter2(ii), Iter2(ii+3), Iter1(ih+3)); + + return true; } int main(int, char**) { @@ -101,5 +106,17 @@ test, bidirectional_iterator >(); test, random_access_iterator >(); - return 0; +#if TEST_STD_VER >= 20 + static_assert(test, forward_iterator>()); + static_assert(test, bidirectional_iterator>()); + static_assert(test, random_access_iterator>()); + static_assert(test, forward_iterator>()); + static_assert(test, bidirectional_iterator>()); + static_assert(test, random_access_iterator>()); + static_assert(test, forward_iterator>()); + static_assert(test, bidirectional_iterator>()); + static_assert(test, random_access_iterator>()); +#endif + + return 0; } diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -369,10 +369,9 @@ "headers": ["algorithm"], "unimplemented": True, }, { - "name": "__cpp_lib_constexpr_misc", - "values": { "c++2a": int(201811) }, - "headers": ["array", "functional", "iterator", "string_view", "tuple", "utility"], - "unimplemented": True, + "name": "__cpp_lib_constexpr_functional", + "values": { "c++2a": int(201907) }, + "headers": ["functional"], }, { "name": "__cpp_lib_constexpr_numeric", "values": { "c++2a": int(201911) },