[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:
@@ -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","",""
|
||||
|
||||
|
@@ -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``
|
||||
------------------------------------------------- -----------------
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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)...))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) },
|
||||
|
||||
Reference in New Issue
Block a user