[llvm-branch-commits] [libcxx] 7b00e9f - [libc++] [P1065] Constexpr invoke, reference_wrapper, mem_fn, not_fn, default_searcher.
Arthur O'Dwyer via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Dec 28 10:29:39 PST 2020
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) },
More information about the llvm-branch-commits
mailing list