Author: Arthur O'Dwyer Date: 2020-12-28T13:24:07-05:00 New Revision: 7b00e9fae3853d4693e608cc52f6d6da5059f5ff
URL: https://github.com/llvm/llvm-project/commit/7b00e9fae3853d4693e608cc52f6d6da5059f5ff DIFF: https://github.com/llvm/llvm-project/commit/7b00e9fae3853d4693e608cc52f6d6da5059f5ff.diff LOG: [libc++] [P1065] Constexpr invoke, reference_wrapper, mem_fn, not_fn, default_searcher. This completes the implementation of P1065 "constexpr INVOKE": http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1065r2.html This doesn't yet complete the implementation of P1032 "Misc constexpr bits," http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1032r1.html but it does complete all of the <functional> bits, which means that we can now set `__cpp_lib_constexpr_functional` for C++20. This could use more constexpr tests for `std::reference_wrapper<T>`, but the existing tests are extremely non-constexpr-friendly and so I don't want to get into that rabbit-hole today. Differential Revision: https://reviews.llvm.org/D93815 Added: libcxx/test/std/utilities/function.objects/func.invoke/invoke_constexpr.pass.cpp Modified: libcxx/docs/Cxx2aStatusPaperStatus.csv libcxx/docs/FeatureTestMacroTable.rst libcxx/include/__functional_base libcxx/include/functional libcxx/include/type_traits libcxx/include/version libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.pass.cpp libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.pass.cpp libcxx/test/std/language.support/support.limits/support.limits.general/tuple.version.pass.cpp libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp libcxx/test/std/utilities/function.objects/func.memfn/member_data.pass.cpp libcxx/test/std/utilities/function.objects/func.memfn/member_function.pass.cpp libcxx/test/std/utilities/function.objects/func.memfn/member_function_const.pass.cpp libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp libcxx/test/std/utilities/function.objects/func.search/func.search.default/default.pass.cpp libcxx/test/std/utilities/function.objects/func.search/func.search.default/default.pred.pass.cpp libcxx/utils/generate_feature_test_macro_components.py Removed: ################################################################################ diff --git a/libcxx/docs/Cxx2aStatusPaperStatus.csv b/libcxx/docs/Cxx2aStatusPaperStatus.csv index c495e0210cf7..fe5b2f5d4771 100644 --- a/libcxx/docs/Cxx2aStatusPaperStatus.csv +++ b/libcxx/docs/Cxx2aStatusPaperStatus.csv @@ -109,7 +109,7 @@ "`P0980 <https://wg21.link/P0980>`__","LWG","Making std::string constexpr","Cologne","","" "`P1004 <https://wg21.link/P1004>`__","LWG","Making std::vector constexpr","Cologne","","" "`P1035 <https://wg21.link/P1035>`__","LWG","Input Range Adaptors","Cologne","","" -"`P1065 <https://wg21.link/P1065>`__","LWG","Constexpr INVOKE","Cologne","","" +"`P1065 <https://wg21.link/P1065>`__","LWG","Constexpr INVOKE","Cologne","|Complete|","12.0" "`P1135 <https://wg21.link/P1135>`__","LWG","The C++20 Synchronization Library","Cologne","|Complete|","11.0" "`P1207 <https://wg21.link/P1207>`__","LWG","Movability of Single-pass Iterators","Cologne","","" "`P1208 <https://wg21.link/P1208>`__","LWG","Adopt source_location for C++20","Cologne","","" diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 091d4b795233..5930cdaffaec 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -194,7 +194,7 @@ Status ------------------------------------------------- ----------------- ``__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 index c84e7eb11567..708c1a23e84b 100644 --- a/libcxx/include/__functional_base +++ b/libcxx/include/__functional_base @@ -382,20 +382,23 @@ private: 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 <class... _ArgTypes> - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename __invoke_of<type&, _ArgTypes...>::type operator() (_ArgTypes&&... __args) const { return _VSTD::__invoke(get(), _VSTD::forward<_ArgTypes>(__args)...); @@ -510,7 +513,7 @@ public: template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference_wrapper<_Tp> ref(_Tp& __t) _NOEXCEPT { @@ -518,7 +521,7 @@ ref(_Tp& __t) _NOEXCEPT } template <class _Tp> -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 @@ ref(reference_wrapper<_Tp> __t) _NOEXCEPT } template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference_wrapper<const _Tp> cref(const _Tp& __t) _NOEXCEPT { @@ -534,7 +537,7 @@ cref(const _Tp& __t) _NOEXCEPT } template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference_wrapper<const _Tp> cref(reference_wrapper<_Tp> __t) _NOEXCEPT { diff --git a/libcxx/include/functional b/libcxx/include/functional index a54868e82220..dbbebaf82017 100644 --- a/libcxx/include/functional +++ b/libcxx/include/functional @@ -213,7 +213,8 @@ public: template <class Predicate> // deprecated in C++17 binary_negate<Predicate> not2(const Predicate& pred); -template <class F> unspecified not_fn(F&& f); // C++17 +template <class F> +constexpr unspecified not_fn(F&& f); // C++17, constexpr in C++20 template<class T> struct is_bind_expression; template<class T> struct is_placeholder; @@ -226,11 +227,12 @@ template <class T> inline constexpr int is_placeholder_v template<class Fn, class... BoundArgs> - unspecified bind(Fn&&, BoundArgs&&...); + constexpr unspecified bind(Fn&&, BoundArgs&&...); // constexpr in C++20 template<class R, class Fn, class... BoundArgs> - unspecified bind(Fn&&, BoundArgs&&...); + constexpr unspecified bind(Fn&&, BoundArgs&&...); // constexpr in C++20 template<class F, class... Args> + constexpr // constexpr in C++20 invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) // C++17 noexcept(is_nothrow_invocable_v<F, Args...>); @@ -376,7 +378,8 @@ public: template <class S, class T> const_mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)() const); // deprecated in C++11, removed in C++17 template <class S, class T, class A> const_mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A) const); // deprecated in C++11, removed in C++17 -template<class R, class T> unspecified mem_fn(R T::*); +template<class R, class T> +constexpr unspecified mem_fn(R T::*); // constexpr in C++20 class bad_function_call : public exception @@ -1288,12 +1291,13 @@ private: 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 <class... _ArgTypes> - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename __invoke_return<type, _ArgTypes...>::type operator() (_ArgTypes&&... __args) const { return _VSTD::__invoke(__f_, _VSTD::forward<_ArgTypes>(__args)...); @@ -1401,7 +1405,7 @@ public: }; template<class _Rp, class _Tp> -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 @@ public: !is_same<typename remove_reference<_Gp>::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 <class ..._Args> - _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 @@ public: } template <class ..._Args> - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type operator()(_Args&& ...__args) const { @@ -2918,13 +2922,13 @@ public: !is_same<typename remove_reference<_Gp>::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 <class ..._Args> - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < is_convertible<typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type, @@ -2938,7 +2942,7 @@ public: } template <class ..._Args> - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < is_convertible<typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type, @@ -2956,7 +2960,7 @@ template<class _Rp, class _Fp, class ..._BoundArgs> struct __is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {}; template<class _Fp, class ..._BoundArgs> -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 @@ bind(_Fp&& __f, _BoundArgs&&... __bound_args) } template<class _Rp, class _Fp, class ..._BoundArgs> -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 @@ bind(_Fp&& __f, _BoundArgs&&... __bound_args) #if _LIBCPP_STD_VER > 14 template <class _Fn, class ..._Args> -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 @@ public: __not_fn_imp() = delete; template <class ..._Args> - _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 <class ..._Args> - _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 <class ..._Args> - _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 @@ public: template <class ..._Args> - _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 @@ public: private: template <class _RawFunc, class = enable_if_t<!is_same<decay_t<_RawFunc>, __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 <class _RawFunc> - friend inline _LIBCPP_INLINE_VISIBILITY + friend inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __not_fn_imp<decay_t<_RawFunc>> not_fn(_RawFunc&&); }; template <class _RawFunc> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __not_fn_imp<decay_t<_RawFunc>> not_fn(_RawFunc&& __fn) { return __not_fn_imp<decay_t<_RawFunc>>(_VSTD::forward<_RawFunc>(__fn)); } @@ -3131,13 +3135,13 @@ __search(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, template<class _ForwardIterator, class _BinaryPredicate = equal_to<>> 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 <typename _ForwardIterator2> - _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 index c1633f19c51f..99b2a8f9f025 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -3584,7 +3584,7 @@ auto __invoke_constexpr(__any, _Args&& ...__args) -> __nat; template <class _Fp, class _A0, class ..._Args, class = __enable_if_bullet1<_Fp, _A0>> 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 @@ _LIBCPP_INVOKE_RETURN((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__a template <class _Fp, class _A0, class ..._Args, class = __enable_if_bullet2<_Fp, _A0>> 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 @@ _LIBCPP_INVOKE_RETURN((__a0.get().*__f)(_VSTD::forward<_Args>(__args)...)) template <class _Fp, class _A0, class ..._Args, class = __enable_if_bullet3<_Fp, _A0>> 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 @@ _LIBCPP_INVOKE_RETURN(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>( template <class _Fp, class _A0, class = __enable_if_bullet4<_Fp, _A0>> 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 @@ _LIBCPP_INVOKE_RETURN(_VSTD::forward<_A0>(__a0).*__f) template <class _Fp, class _A0, class = __enable_if_bullet5<_Fp, _A0>> 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 @@ _LIBCPP_INVOKE_RETURN(__a0.get().*__f) template <class _Fp, class _A0, class = __enable_if_bullet6<_Fp, _A0>> 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 @@ _LIBCPP_INVOKE_RETURN((*_VSTD::forward<_A0>(__a0)).*__f) template <class _Fp, class ..._Args> 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 index e32f47ae837a..dde6ca165b35 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -46,8 +46,7 @@ __cpp_lib_clamp 201603L <algorithm> __cpp_lib_complex_udls 201309L <complex> __cpp_lib_concepts 201806L <concepts> __cpp_lib_constexpr_dynamic_alloc 201907L <memory> -__cpp_lib_constexpr_misc 201811L <array> <functional> <iterator> - <string_view> <tuple> <utility> +__cpp_lib_constexpr_functional 201907L <functional> __cpp_lib_constexpr_numeric 201911L <numeric> __cpp_lib_constexpr_swap_algorithms 201806L <algorithm> __cpp_lib_constexpr_utility 201811L <utility> @@ -254,7 +253,7 @@ __cpp_lib_void_t 201411L <type_traits> # 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 index 933420be50c9..c2e831a3af31 100644 --- 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 index a29a1d708a30..2b556010f00e 100644 --- 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 index 4e68cf9a7232..0c128f5a46de 100644 --- 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 index 816083e0d7f3..1fca20d41f8c 100644 --- 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 <string_view> -/* 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 <string_view> @@ -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 index 5c1e6580c57d..e4c3d54d1982 100644 --- 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 index e595a99a749f..63f755e66047 100644 --- 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 index 783c5449038c..e37907185db1 100644 --- 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 index 000000000000..8bfc7428fad9 --- /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 + +// <functional> + +// template<class F, class... Args> +// constexpr // constexpr in C++20 +// invoke_result_t<F, Args...> 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 <functional> +#include <type_traits> +#include <utility> // for std::move +#include <cassert> + +#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 <class Signature, class Expect, class Functor> +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<Functor>(f), std::move(arg)) + ) DeducedReturnType; + static_assert((std::is_same<DeducedReturnType, Expect>::value), ""); + + // Check that result_of_t matches Expect. + typedef typename std::result_of<ClassFunc&&(Functor&&, NonCopyable&&)>::type + ResultOfReturnType; + static_assert((std::is_same<ResultOfReturnType, Expect>::value), ""); + + // Run invoke and check the return value. + DeducedReturnType ret = + std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg)); + assert(ret == 42); +} + +template <class Expect, class Functor> +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<Functor>(f)) + ) DeducedReturnType; + static_assert((std::is_same<DeducedReturnType, Expect>::value), ""); + + // Check that result_of_t matches Expect. + typedef typename std::result_of<ClassFunc&&(Functor&&)>::type + ResultOfReturnType; + static_assert((std::is_same<ResultOfReturnType, Expect>::value), ""); + + // Run invoke and check the return value. + DeducedReturnType ret = + std::invoke(func_ptr, std::forward<Functor>(f)); + assert(ret == 42); +} + +template <class Expect, class Functor> +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<Functor>(f), std::move(arg)) + ) DeducedReturnType; + static_assert((std::is_same<DeducedReturnType, Expect>::value), ""); + + // Check that result_of_t matches Expect. + typedef typename std::result_of<Functor&&(NonCopyable&&)>::type + ResultOfReturnType; + static_assert((std::is_same<ResultOfReturnType, Expect>::value), ""); + + // Run invoke and check the return value. + DeducedReturnType ret = std::invoke(std::forward<Functor>(f), std::move(arg)); + assert(ret == 42); +} + +constexpr bool bullet_one_two_tests() { + { + TestClass cl(42); + test_b12<int&(NonCopyable&&) &, int&>(cl); + test_b12<int const&(NonCopyable&&) const &, int const&>(cl); + + test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl)); + test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl)); + } + { + DerivedFromTestClass cl(42); + test_b12<int&(NonCopyable&&) &, int&>(cl); + test_b12<int const&(NonCopyable&&) const &, int const&>(cl); + + test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl)); + test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl)); + } + { + TestClass cl_obj(42); + std::reference_wrapper<TestClass> cl(cl_obj); + test_b12<int&(NonCopyable&&) &, int&>(cl); + test_b12<int const&(NonCopyable&&) const &, int const&>(cl); + + test_b12<int&(NonCopyable&&) &, int&>(std::move(cl)); + test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl)); + } + { + DerivedFromTestClass cl_obj(42); + std::reference_wrapper<DerivedFromTestClass> cl(cl_obj); + test_b12<int&(NonCopyable&&) &, int&>(cl); + test_b12<int const&(NonCopyable&&) const &, int const&>(cl); + + test_b12<int&(NonCopyable&&) &, int&>(std::move(cl)); + test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl)); + } + { + TestClass cl_obj(42); + TestClass *cl = &cl_obj; + test_b12<int&(NonCopyable&&) &, int&>(cl); + test_b12<int const&(NonCopyable&&) const &, int const&>(cl); + } + { + DerivedFromTestClass cl_obj(42); + DerivedFromTestClass *cl = &cl_obj; + test_b12<int&(NonCopyable&&) &, int&>(cl); + test_b12<int const&(NonCopyable&&) const &, int const&>(cl); + } + return true; +} + +constexpr bool bullet_three_four_tests() { + { + typedef TestClass Fn; + Fn cl(42); + test_b34<int&>(cl); + test_b34<int const&>(static_cast<Fn const&>(cl)); + + test_b34<int&&>(static_cast<Fn &&>(cl)); + test_b34<int const&&>(static_cast<Fn const&&>(cl)); + } + { + typedef DerivedFromTestClass Fn; + Fn cl(42); + test_b34<int&>(cl); + test_b34<int const&>(static_cast<Fn const&>(cl)); + + test_b34<int&&>(static_cast<Fn &&>(cl)); + test_b34<int const&&>(static_cast<Fn const&&>(cl)); + } + { + typedef TestClass Fn; + Fn cl(42); + test_b34<int&>(std::reference_wrapper<Fn>(cl)); + test_b34<int const&>(std::reference_wrapper<Fn const>(cl)); + } + { + typedef DerivedFromTestClass Fn; + Fn cl(42); + test_b34<int&>(std::reference_wrapper<Fn>(cl)); + test_b34<int const&>(std::reference_wrapper<Fn const>(cl)); + } + { + typedef TestClass Fn; + Fn cl_obj(42); + Fn* cl = &cl_obj; + test_b34<int&>(cl); + test_b34<int const&>(static_cast<Fn const*>(cl)); + } + { + typedef DerivedFromTestClass Fn; + Fn cl_obj(42); + Fn* cl = &cl_obj; + test_b34<int&>(cl); + test_b34<int const&>(static_cast<Fn const*>(cl)); + } + return true; +} + +constexpr bool bullet_five_tests() { + using FooType = const int&(NonCopyable&&); + { + FooType& fn = foo; + test_b5<const int &>(fn); + } + { + FooType* fn = foo; + test_b5<const int &>(fn); + } + { + typedef TestClass Fn; + Fn cl(42); + test_b5<int&>(cl); + test_b5<int const&>(static_cast<Fn const&>(cl)); + + test_b5<int&&>(static_cast<Fn &&>(cl)); + test_b5<int const&&>(static_cast<Fn const&&>(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 index 0c340072da5a..5cb4d2d28ab5 100644 --- 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 @@ struct A }; template <class F> -void +TEST_CONSTEXPR_CXX20 bool test(F f) { { @@ -36,11 +36,16 @@ test(F f) 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 index a271c067008b..88d4108e10ac 100644 --- 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 <class F> -void +TEST_CONSTEXPR_CXX20 bool test0(F f) { { @@ -35,10 +35,11 @@ test0(F f) const F& cf = f; assert(cf(ap) == 'a'); } + return true; } template <class F> -void +TEST_CONSTEXPR_CXX20 bool test1(F f) { { @@ -49,10 +50,11 @@ test1(F f) const F& cf = f; assert(cf(ap, 2) == 'b'); } + return true; } template <class F> -void +TEST_CONSTEXPR_CXX20 bool test2(F f) { { @@ -63,6 +65,7 @@ test2(F f) const F& cf = f; assert(cf(ap, 2, 3.5) == 'c'); } + return true; } int main(int, char**) @@ -74,5 +77,11 @@ int main(int, char**) 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 index 006a5bec2d39..057998c7e6e5 100644 --- 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 <class F> -void +TEST_CONSTEXPR_CXX20 bool test0(F f) { { @@ -37,10 +37,11 @@ test0(F f) const F& cf = f; assert(cf(ap) == 'a'); } + return true; } template <class F> -void +TEST_CONSTEXPR_CXX20 bool test1(F f) { { @@ -53,10 +54,11 @@ test1(F f) const F& cf = f; assert(cf(ap, 2) == 'b'); } + return true; } template <class F> -void +TEST_CONSTEXPR_CXX20 bool test2(F f) { { @@ -69,6 +71,7 @@ test2(F f) const F& cf = f; assert(cf(ap, 2, 3.5) == 'c'); } + return true; } int main(int, char**) @@ -77,5 +80,11 @@ int main(int, char**) 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 index 75f7f9fd4f02..bb86dc9a8b6f 100644 --- 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 <class Ret = bool> struct MoveOnlyCallable { MoveOnlyCallable(MoveOnlyCallable const&) = delete; - MoveOnlyCallable(MoveOnlyCallable&& other) + constexpr MoveOnlyCallable(MoveOnlyCallable&& other) : value(other.value) { other.value = !other.value; } template <class ...Args> - 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 <class Ret = bool> 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 <class ...Args> - 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 <class Ret = bool> 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 <class ...Args> - 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 @@ struct ConstCallable { template <class Ret = bool> struct NoExceptCallable { - NoExceptCallable(NoExceptCallable const& other) + constexpr NoExceptCallable(NoExceptCallable const& other) : value(other.value) {} template <class ...Args> - Ret operator()(Args&&...) noexcept { return Ret{value}; } + constexpr Ret operator()(Args&&...) noexcept { return Ret{value}; } template <class ...Args> - 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 <class ...Args> - 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 <class ...Args> - 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; }; @@ -210,7 +210,7 @@ struct EvilBool { friend struct CopyCallable<EvilBool>; friend struct NoExceptCallable<EvilBool>; - explicit EvilBool(bool x) : value(x) {} + constexpr explicit EvilBool(bool x) : value(x) {} EvilBool& operator=(EvilBool const& other) = default; public: @@ -223,14 +223,14 @@ struct ExplicitBool { ExplicitBool(ExplicitBool const&) = default; ExplicitBool(ExplicitBool&&) = default; - explicit operator bool() const { return value; } + constexpr explicit operator bool() const { return value; } private: friend struct MoveOnlyCallable<ExplicitBool>; friend struct CopyCallable<ExplicitBool>; - 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; } @@ -244,7 +244,7 @@ struct NoExceptEvilBool { 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}; @@ -255,7 +255,8 @@ struct NoExceptEvilBool { -void constructor_tests() +TEST_CONSTEXPR_CXX20 +bool constructor_tests() { { using T = MoveOnlyCallable<bool>; @@ -335,6 +336,7 @@ void constructor_tests() assert(ret() == true); #endif // _LIBCPP_VERSION } + return true; } void return_type_tests() @@ -369,7 +371,8 @@ void return_type_tests() // 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); @@ -408,6 +411,7 @@ void other_callable_types_test() assert(ret(&mt) == false); assert(ret(&mf) == true); } + return true; } void throws_in_constructor_test() @@ -439,7 +443,8 @@ void throws_in_constructor_test() #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<T>::value, ""); // callable only with no args @@ -463,9 +468,11 @@ void call_operator_sfinae_test() { static_assert(std::is_invocable<T, bool>::value, ""); static_assert(!std::is_invocable<T, std::string>::value, ""); } + return true; } -void call_operator_forwarding_test() +TEST_CONSTEXPR_CXX20 +bool call_operator_forwarding_test() { using Fn = ForwardingCallObject; Fn::State st; @@ -538,20 +545,23 @@ void call_operator_forwarding_test() assert(st.check_call<int&&>(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"}); - assert((st.check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_LValue))); - std::move(obj)(42, std::move(y), s, std::string{"foo"}); - assert((st.check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_RValue))); - c_obj(42, std::move(y), s, std::string{"foo"}); - assert((st.check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const | CT_LValue))); - std::move(c_obj)(42, std::move(y), s, std::string{"foo"}); - assert((st.check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const | CT_RValue))); + String s = "abc"; + obj(42, std::move(y), s, String{"foo"}); + assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_LValue))); + std::move(obj)(42, std::move(y), s, String{"foo"}); + assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_RValue))); + c_obj(42, std::move(y), s, String{"foo"}); + assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const | CT_LValue))); + std::move(c_obj)(42, std::move(y), s, String{"foo"}); + assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const | CT_RValue))); } + return true; } -void call_operator_noexcept_test() +TEST_CONSTEXPR_CXX20 +bool call_operator_noexcept_test() { { using T = ConstCallable<bool>; @@ -589,19 +599,22 @@ void call_operator_noexcept_test() 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**) @@ -615,5 +628,14 @@ int main(int, char**) 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 index 04c2de6bda50..9c51b3ac39f3 100644 --- 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 <typename Iter1, typename Iter2> +TEST_CONSTEXPR_CXX20 void do_search(Iter1 b1, Iter1 e1, Iter2 b2, Iter2 e2, Iter1 result) { std::default_searcher<Iter2> s{b2, e2}; assert(result == std::search(b1, e1, s)); } template <class Iter1, class Iter2> -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 @@ test() 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 @@ int main(int, char**) { test<random_access_iterator<const int*>, bidirectional_iterator<const int*> >(); test<random_access_iterator<const int*>, random_access_iterator<const int*> >(); - return 0; +#if TEST_STD_VER >= 20 + static_assert(test<forward_iterator<const int*>, forward_iterator<const int*>>()); + static_assert(test<forward_iterator<const int*>, bidirectional_iterator<const int*>>()); + static_assert(test<forward_iterator<const int*>, random_access_iterator<const int*>>()); + static_assert(test<bidirectional_iterator<const int*>, forward_iterator<const int*>>()); + static_assert(test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>>()); + static_assert(test<bidirectional_iterator<const int*>, random_access_iterator<const int*>>()); + static_assert(test<random_access_iterator<const int*>, forward_iterator<const int*>>()); + static_assert(test<random_access_iterator<const int*>, bidirectional_iterator<const int*>>()); + static_assert(test<random_access_iterator<const int*>, random_access_iterator<const int*>>()); +#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 index 6f3bdb5dfbae..bc9ba2f860b4 100644 --- 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 <class T> - 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 <typename Iter1, typename Iter2> -void do_search(Iter1 b1, Iter1 e1, Iter2 b2, Iter2 e2, Iter1 result, unsigned max_count) { - std::default_searcher<Iter2, count_equal> 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<Iter2, count_equal> 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 <class Iter1, class Iter2> -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 @@ int main(int, char**) { test<random_access_iterator<const int*>, bidirectional_iterator<const int*> >(); test<random_access_iterator<const int*>, random_access_iterator<const int*> >(); - return 0; +#if TEST_STD_VER >= 20 + static_assert(test<forward_iterator<const int*>, forward_iterator<const int*>>()); + static_assert(test<forward_iterator<const int*>, bidirectional_iterator<const int*>>()); + static_assert(test<forward_iterator<const int*>, random_access_iterator<const int*>>()); + static_assert(test<bidirectional_iterator<const int*>, forward_iterator<const int*>>()); + static_assert(test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>>()); + static_assert(test<bidirectional_iterator<const int*>, random_access_iterator<const int*>>()); + static_assert(test<random_access_iterator<const int*>, forward_iterator<const int*>>()); + static_assert(test<random_access_iterator<const int*>, bidirectional_iterator<const int*>>()); + static_assert(test<random_access_iterator<const int*>, random_access_iterator<const int*>>()); +#endif + + return 0; } diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index 5010c080c759..091fea431384 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -369,10 +369,9 @@ def add_version_header(tc): "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) }, _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits