[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
This commit is contained in:
Arthur O'Dwyer
2020-12-25 14:48:39 -05:00
parent 30f589c912
commit 7b00e9fae3
21 changed files with 538 additions and 319 deletions

View File

@@ -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","",""
1 Paper # Group Paper Name Meeting Status First released version
109 `P0980 <https://wg21.link/P0980>`__ LWG Making std::string constexpr Cologne
110 `P1004 <https://wg21.link/P1004>`__ LWG Making std::vector constexpr Cologne
111 `P1035 <https://wg21.link/P1035>`__ LWG Input Range Adaptors Cologne
112 `P1065 <https://wg21.link/P1065>`__ LWG Constexpr INVOKE Cologne |Complete| 12.0
113 `P1135 <https://wg21.link/P1135>`__ LWG The C++20 Synchronization Library Cologne |Complete| 11.0
114 `P1207 <https://wg21.link/P1207>`__ LWG Movability of Single-pass Iterators Cologne
115 `P1208 <https://wg21.link/P1208>`__ LWG Adopt source_location for C++20 Cologne

View File

@@ -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``
------------------------------------------------- -----------------

View File

@@ -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
{

View File

@@ -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
{

View File

@@ -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)...))

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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 @@ private:
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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -369,10 +369,9 @@ feature_test_macros = sorted([ add_version_header(x) for x in [
"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) },