diff --git a/libcxx/docs/Cxx2aStatusIssuesStatus.csv b/libcxx/docs/Cxx2aStatusIssuesStatus.csv --- a/libcxx/docs/Cxx2aStatusIssuesStatus.csv +++ b/libcxx/docs/Cxx2aStatusIssuesStatus.csv @@ -147,7 +147,7 @@ "`3158 `__","``tuple(allocator_arg_t, const Alloc&)``\ should be conditionally explicit","Cologne","","" "`3169 `__","``ranges``\ permutation generators discard useful information","Cologne","","" "`3183 `__","Normative permission to specialize Ranges variable templates","Cologne","","" -"`3184 `__","Inconsistencies in ``bind_front``\ wording","Cologne","","" +"`3184 `__","Inconsistencies in ``bind_front``\ wording","Cologne","|Complete|","13.0" "`3185 `__","Uses-allocator construction functions missing ``constexpr``\ and ``noexcept``\ ","Cologne","","" "`3186 `__","``ranges``\ removal, partition, and ``partial_sort_copy``\ algorithms discard useful information","Cologne","","" "`3187 `__","`P0591R4 `__ reverted DR 2586 fixes to ``scoped_allocator_adaptor::construct()``\ ","Cologne","","" diff --git a/libcxx/docs/Cxx2aStatusPaperStatus.csv b/libcxx/docs/Cxx2aStatusPaperStatus.csv --- a/libcxx/docs/Cxx2aStatusPaperStatus.csv +++ b/libcxx/docs/Cxx2aStatusPaperStatus.csv @@ -51,7 +51,7 @@ "`P1120R0 `__","CWG","Consistency improvements for <=> and other comparison operators","Rapperswil","","" "","","","","","" "`P0318R1 `__","LWG","unwrap_ref_decay and unwrap_reference","San Diego","|Complete|","8.0" -"`P0356R5 `__","LWG","Simplified partial function application","San Diego","* *","" +"`P0356R5 `__","LWG","Simplified partial function application","San Diego","|Complete|","13.0" "`P0357R3 `__","LWG","reference_wrapper for incomplete types","San Diego","|Complete|","8.0" "`P0482R6 `__","CWG","char8_t: A type for UTF-8 characters and strings","San Diego","|In Progress|","" "`P0487R1 `__","LWG","Fixing ``operator>>(basic_istream&, CharT*)``\ (LWG 2499)","San Diego","|Complete|","8.0" @@ -128,7 +128,7 @@ "`P1643 `__","LWG","Add wait/notify to atomic_ref","Cologne","","" "`P1644 `__","LWG","Add wait/notify to atomic","Cologne","","" "`P1650 `__","LWG","Output std::chrono::days with 'd' suffix","Cologne","","" -"`P1651 `__","LWG","bind_front should not unwrap reference_wrapper","Cologne","","" +"`P1651 `__","LWG","bind_front should not unwrap reference_wrapper","Cologne","|Complete|","13.0" "`P1652 `__","LWG","Printf corner cases in std::format","Cologne","","" "`P1661 `__","LWG","Remove dedicated precalculated hash lookup interface","Cologne","|Nothing To Do|","" "`P1754 `__","LWG","Rename concepts to standard_case for C++20, while we still can","Cologne","|In Progress|","" diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -188,7 +188,7 @@ ------------------------------------------------- ----------------- ``__cpp_lib_barrier`` ``201907L`` ------------------------------------------------- ----------------- - ``__cpp_lib_bind_front`` *unimplemented* + ``__cpp_lib_bind_front`` ``201907L`` ------------------------------------------------- ----------------- ``__cpp_lib_bit_cast`` *unimplemented* ------------------------------------------------- ----------------- diff --git a/libcxx/include/__string b/libcxx/include/__string --- a/libcxx/include/__string +++ b/libcxx/include/__string @@ -953,7 +953,7 @@ template inline _LIBCPP_CONSTEXPR_AFTER_CXX11 const _CharT * __search_substring(const _CharT *__first1, const _CharT *__last1, - const _CharT *__first2, const _CharT *__last2) { + const _CharT *__first2, const _CharT *__last2) _NOEXCEPT { // Take advantage of knowing source and pattern lengths. // Stop short when source is smaller than pattern. const ptrdiff_t __len2 = __last2 - __first2; diff --git a/libcxx/include/functional b/libcxx/include/functional --- a/libcxx/include/functional +++ b/libcxx/include/functional @@ -2989,61 +2989,107 @@ return _VSTD::__invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)...); } -template -class _LIBCPP_TEMPLATE_VIS __not_fn_imp { - _DecayFunc __fd; - -public: - __not_fn_imp() = delete; - - template - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 - auto operator()(_Args&& ...__args) & - noexcept(noexcept(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...))) - -> decltype( !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...)) - { return !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...); } - - template - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 - auto operator()(_Args&& ...__args) && - noexcept(noexcept(!_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...))) - -> decltype( !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...)) - { return !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...); } - - template - _LIBCPP_INLINE_VISIBILITY _LIBCPP_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)...)) - { return !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...); } - +template::value>::type> +struct __perfect_forward_impl; + +template +struct __perfect_forward_impl<_Op, __tuple_types<_Bound...>, __tuple_indices<_Idxs...>> +{ + _VSTD::tuple<_Bound...> __bound; + + template + _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) & + noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(__bound)..., _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op::__call(_VSTD::get<_Idxs>(__bound)..., _VSTD::forward<_Args>(__args)...)) + {return _Op::__call(_VSTD::get<_Idxs>(__bound)..., _VSTD::forward<_Args>(__args)...);} + + template + _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) const& + noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(__bound)..., _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op::__call(_VSTD::get<_Idxs>(__bound)..., _VSTD::forward<_Args>(__args)...)) + {return _Op::__call(_VSTD::get<_Idxs>(__bound)..., _VSTD::forward<_Args>(__args)...);} + + template + _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) && + noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound))..., + _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound))..., + _VSTD::forward<_Args>(__args)...)) + {return _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound))..., + _VSTD::forward<_Args>(__args)...);} + + template + _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) const&& + noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound))..., + _VSTD::forward<_Args>(__args)...))) + -> decltype( _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound))..., + _VSTD::forward<_Args>(__args)...)) + {return _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound))..., + _VSTD::forward<_Args>(__args)...);} + + template>::type, + class = _EnableIf<_VSTD::is_copy_constructible_v<_Fn>>> + constexpr __perfect_forward_impl(__perfect_forward_impl const& __other) + : __bound(__other.__bound) {} + + template>::type, + class = _EnableIf<_VSTD::is_move_constructible_v<_Fn>>> + constexpr __perfect_forward_impl(__perfect_forward_impl && __other) + : __bound(_VSTD::move(__other.__bound)) {} + + template + explicit constexpr __perfect_forward_impl(_BoundArgs&&... __bound) : + __bound(_VSTD::forward<_BoundArgs>(__bound)...) { } +}; + +template +using __perfect_forward = + __perfect_forward_impl<_Op, __tuple_types...>>; + +struct __not_fn_op +{ + template + static _LIBCPP_CONSTEXPR_AFTER_CXX17 auto __call(_Args&&... __args) + noexcept(noexcept(!_VSTD::invoke(_VSTD::forward<_Args>(__args)...))) + -> decltype( !_VSTD::invoke(_VSTD::forward<_Args>(__args)...)) + { return !_VSTD::invoke(_VSTD::forward<_Args>(__args)...); } +}; + +template, _Fn> && + is_move_constructible_v<_Fn>>> +_LIBCPP_CONSTEXPR_AFTER_CXX17 auto not_fn(_Fn&& __f) +{ + return __perfect_forward<__not_fn_op, _Fn>(_VSTD::forward<_Fn>(__f)); +} - template - _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)...)) - { return !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...); } +#endif // _LIBCPP_STD_VER > 14 -private: - template , __not_fn_imp>::value>> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 - explicit __not_fn_imp(_RawFunc&& __rf) - : __fd(_VSTD::forward<_RawFunc>(__rf)) {} +#if _LIBCPP_STD_VER > 17 - template - friend inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 - __not_fn_imp> not_fn(_RawFunc&&); +struct __bind_front_op +{ + template + constexpr static auto __call(_Args&&... __args) + noexcept(noexcept(_VSTD::invoke(_VSTD::forward<_Args>(__args)...))) + -> decltype( _VSTD::invoke(_VSTD::forward<_Args>(__args)...)) + { return _VSTD::invoke(_VSTD::forward<_Args>(__args)...); } }; -template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -__not_fn_imp> not_fn(_RawFunc&& __fn) { - return __not_fn_imp>(_VSTD::forward<_RawFunc>(__fn)); +template, _Fn>, + is_move_constructible>, + is_constructible, _Args>..., + is_move_constructible>... + >::value>> +constexpr auto bind_front(_Fn&& __f, _Args&&... __args) +{ + return __perfect_forward<__bind_front_op, _Fn, _Args...>(_VSTD::forward<_Fn>(__f), + _VSTD::forward<_Args>(__args)...); } -#endif +#endif // _LIBCPP_STD_VER > 17 // struct hash in diff --git a/libcxx/include/string b/libcxx/include/string --- a/libcxx/include/string +++ b/libcxx/include/string @@ -262,49 +262,49 @@ size_type find(const basic_string& str, size_type pos = 0) const noexcept; template - size_type find(const T& t, size_type pos = 0) const; // C++17 + size_type find(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension size_type find(const value_type* s, size_type pos, size_type n) const noexcept; size_type find(const value_type* s, size_type pos = 0) const noexcept; size_type find(value_type c, size_type pos = 0) const noexcept; size_type rfind(const basic_string& str, size_type pos = npos) const noexcept; template - size_type rfind(const T& t, size_type pos = npos) const; // C++17 + size_type rfind(const T& t, size_type pos = npos) const noexcept; // C++17, noexcept as an extension size_type rfind(const value_type* s, size_type pos, size_type n) const noexcept; size_type rfind(const value_type* s, size_type pos = npos) const noexcept; size_type rfind(value_type c, size_type pos = npos) const noexcept; size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept; template - size_type find_first_of(const T& t, size_type pos = 0) const; // C++17 + size_type find_first_of(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension size_type find_first_of(const value_type* s, size_type pos, size_type n) const noexcept; size_type find_first_of(const value_type* s, size_type pos = 0) const noexcept; size_type find_first_of(value_type c, size_type pos = 0) const noexcept; size_type find_last_of(const basic_string& str, size_type pos = npos) const noexcept; template - size_type find_last_of(const T& t, size_type pos = npos) const noexcept; // C++17 + size_type find_last_of(const T& t, size_type pos = npos) const noexcept noexcept; // C++17, noexcept as an extension size_type find_last_of(const value_type* s, size_type pos, size_type n) const noexcept; size_type find_last_of(const value_type* s, size_type pos = npos) const noexcept; size_type find_last_of(value_type c, size_type pos = npos) const noexcept; size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept; template - size_type find_first_not_of(const T& t, size_type pos = 0) const; // C++17 + size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension size_type find_first_not_of(const value_type* s, size_type pos, size_type n) const noexcept; size_type find_first_not_of(const value_type* s, size_type pos = 0) const noexcept; size_type find_first_not_of(value_type c, size_type pos = 0) const noexcept; size_type find_last_not_of(const basic_string& str, size_type pos = npos) const noexcept; template - size_type find_last_not_of(const T& t, size_type pos = npos) const; // C++17 + size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept; // C++17, noexcept as an extension size_type find_last_not_of(const value_type* s, size_type pos, size_type n) const noexcept; size_type find_last_not_of(const value_type* s, size_type pos = npos) const noexcept; size_type find_last_not_of(value_type c, size_type pos = npos) const noexcept; int compare(const basic_string& str) const noexcept; template - int compare(const T& t) const noexcept; // C++17 + int compare(const T& t) const noexcept; // C++17, noexcept as an extension int compare(size_type pos1, size_type n1, const basic_string& str) const; template int compare(size_type pos1, size_type n1, const T& t) const; // C++17 @@ -1284,7 +1284,7 @@ __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, size_type > - find(const _Tp& __t, size_type __pos = 0) const; + find(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; @@ -1300,7 +1300,7 @@ __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, size_type > - rfind(const _Tp& __t, size_type __pos = npos) const; + rfind(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type rfind(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; @@ -1316,7 +1316,7 @@ __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, size_type > - find_first_of(const _Tp& __t, size_type __pos = 0) const; + find_first_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; size_type find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_first_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; @@ -1333,7 +1333,7 @@ __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, size_type > - find_last_of(const _Tp& __t, size_type __pos = npos) const; + find_last_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; size_type find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_last_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; @@ -1350,7 +1350,7 @@ __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, size_type > - find_first_not_of(const _Tp &__t, size_type __pos = 0) const; + find_first_not_of(const _Tp &__t, size_type __pos = 0) const _NOEXCEPT; size_type find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_first_not_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; @@ -1367,7 +1367,7 @@ __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, size_type > - find_last_not_of(const _Tp& __t, size_type __pos = npos) const; + find_last_not_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; size_type find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_last_not_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; @@ -1384,7 +1384,7 @@ __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int > - compare(const _Tp &__t) const; + compare(const _Tp &__t) const _NOEXCEPT; template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS @@ -3543,7 +3543,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type > basic_string<_CharT, _Traits, _Allocator>::find(const _Tp &__t, - size_type __pos) const + size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return __str_find @@ -3601,7 +3601,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type > basic_string<_CharT, _Traits, _Allocator>::rfind(const _Tp& __t, - size_type __pos) const + size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return __str_rfind @@ -3659,7 +3659,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type > basic_string<_CharT, _Traits, _Allocator>::find_first_of(const _Tp& __t, - size_type __pos) const + size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return __str_find_first_of @@ -3717,7 +3717,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type > basic_string<_CharT, _Traits, _Allocator>::find_last_of(const _Tp& __t, - size_type __pos) const + size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return __str_find_last_of @@ -3775,7 +3775,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type > basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const _Tp& __t, - size_type __pos) const + size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return __str_find_first_not_of @@ -3834,7 +3834,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type > basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const _Tp& __t, - size_type __pos) const + size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return __str_find_last_not_of @@ -3871,7 +3871,7 @@ __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int > -basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const +basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const _NOEXCEPT { __self_view __sv = __t; size_t __lhs_sz = size(); diff --git a/libcxx/include/string_view b/libcxx/include/string_view --- a/libcxx/include/string_view +++ b/libcxx/include/string_view @@ -119,28 +119,28 @@ const charT* s, size_type n2) const; constexpr size_type find(basic_string_view s, size_type pos = 0) const noexcept; constexpr size_type find(charT c, size_type pos = 0) const noexcept; - constexpr size_type find(const charT* s, size_type pos, size_type n) const; - constexpr size_type find(const charT* s, size_type pos = 0) const; + constexpr size_type find(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension + constexpr size_type find(const charT* s, size_type pos = 0) const noexcept; // noexcept as an extension constexpr size_type rfind(basic_string_view s, size_type pos = npos) const noexcept; constexpr size_type rfind(charT c, size_type pos = npos) const noexcept; - constexpr size_type rfind(const charT* s, size_type pos, size_type n) const; - constexpr size_type rfind(const charT* s, size_type pos = npos) const; + constexpr size_type rfind(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension + constexpr size_type rfind(const charT* s, size_type pos = npos) const noexcept; // noexcept as an extension constexpr size_type find_first_of(basic_string_view s, size_type pos = 0) const noexcept; constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept; - constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const; - constexpr size_type find_first_of(const charT* s, size_type pos = 0) const; + constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension + constexpr size_type find_first_of(const charT* s, size_type pos = 0) const noexcept; // noexcept as an extension constexpr size_type find_last_of(basic_string_view s, size_type pos = npos) const noexcept; constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept; - constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const; - constexpr size_type find_last_of(const charT* s, size_type pos = npos) const; + constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension + constexpr size_type find_last_of(const charT* s, size_type pos = npos) const noexcept; // noexcept as an extension constexpr size_type find_first_not_of(basic_string_view s, size_type pos = 0) const noexcept; constexpr size_type find_first_not_of(charT c, size_type pos = 0) const noexcept; - constexpr size_type find_first_not_of(const charT* s, size_type pos, size_type n) const; - constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const; + constexpr size_type find_first_not_of(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension + constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const noexcept; // noexcept as an extension constexpr size_type find_last_not_of(basic_string_view s, size_type pos = npos) const noexcept; constexpr size_type find_last_not_of(charT c, size_type pos = npos) const noexcept; - constexpr size_type find_last_not_of(const charT* s, size_type pos, size_type n) const; - constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const; + constexpr size_type find_last_not_of(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension + constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const noexcept; // noexcept as an extension constexpr bool starts_with(basic_string_view s) const noexcept; // C++20 constexpr bool starts_with(charT c) const noexcept; // C++20 @@ -431,7 +431,7 @@ } _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY - size_type find(const _CharT* __s, size_type __pos, size_type __n) const + size_type find(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find(): received nullptr"); return __str_find @@ -439,7 +439,7 @@ } _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY - size_type find(const _CharT* __s, size_type __pos = 0) const + size_type find(const _CharT* __s, size_type __pos = 0) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string_view::find(): received nullptr"); return __str_find @@ -463,7 +463,7 @@ } _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY - size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const + size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::rfind(): received nullptr"); return __str_rfind @@ -471,7 +471,7 @@ } _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY - size_type rfind(const _CharT* __s, size_type __pos=npos) const + size_type rfind(const _CharT* __s, size_type __pos=npos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string_view::rfind(): received nullptr"); return __str_rfind @@ -492,7 +492,7 @@ { return find(__c, __pos); } _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY - size_type find_first_of(const _CharT* __s, size_type __pos, size_type __n) const + size_type find_first_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_of(): received nullptr"); return __str_find_first_of @@ -500,7 +500,7 @@ } _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY - size_type find_first_of(const _CharT* __s, size_type __pos=0) const + size_type find_first_of(const _CharT* __s, size_type __pos=0) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string_view::find_first_of(): received nullptr"); return __str_find_first_of @@ -521,7 +521,7 @@ { return rfind(__c, __pos); } _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY - size_type find_last_of(const _CharT* __s, size_type __pos, size_type __n) const + size_type find_last_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_of(): received nullptr"); return __str_find_last_of @@ -529,7 +529,7 @@ } _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY - size_type find_last_of(const _CharT* __s, size_type __pos=npos) const + size_type find_last_of(const _CharT* __s, size_type __pos=npos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string_view::find_last_of(): received nullptr"); return __str_find_last_of @@ -553,7 +553,7 @@ } _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY - size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const + size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_not_of(): received nullptr"); return __str_find_first_not_of @@ -561,7 +561,7 @@ } _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY - size_type find_first_not_of(const _CharT* __s, size_type __pos=0) const + size_type find_first_not_of(const _CharT* __s, size_type __pos=0) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string_view::find_first_not_of(): received nullptr"); return __str_find_first_not_of @@ -585,7 +585,7 @@ } _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY - size_type find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const + size_type find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_not_of(): received nullptr"); return __str_find_last_not_of @@ -593,7 +593,7 @@ } _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY - size_type find_last_not_of(const _CharT* __s, size_type __pos=npos) const + size_type find_last_not_of(const _CharT* __s, size_type __pos=npos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string_view::find_last_not_of(): received nullptr"); return __str_find_last_not_of diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -288,7 +288,7 @@ # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier) # define __cpp_lib_barrier 201907L # endif -// # define __cpp_lib_bind_front 201907L +# define __cpp_lib_bind_front 201907L // # define __cpp_lib_bit_cast 201806L // # define __cpp_lib_bitops 201907L # define __cpp_lib_bounded_array_traits 201902L diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.pass.cpp @@ -174,17 +174,11 @@ #elif TEST_STD_VER == 20 -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_bind_front -# error "__cpp_lib_bind_front should be defined in c++20" -# endif -# if __cpp_lib_bind_front != 201907L -# error "__cpp_lib_bind_front should have the value 201907L in c++20" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_bind_front -# error "__cpp_lib_bind_front should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_bind_front +# error "__cpp_lib_bind_front should be defined in c++20" +# endif +# if __cpp_lib_bind_front != 201907L +# error "__cpp_lib_bind_front should have the value 201907L in c++20" # endif # if !defined(_LIBCPP_VERSION) @@ -257,17 +251,11 @@ #elif TEST_STD_VER > 20 -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_bind_front -# error "__cpp_lib_bind_front should be defined in c++2b" -# endif -# if __cpp_lib_bind_front != 201907L -# error "__cpp_lib_bind_front should have the value 201907L in c++2b" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_bind_front -# error "__cpp_lib_bind_front should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_bind_front +# error "__cpp_lib_bind_front should be defined in c++2b" +# endif +# if __cpp_lib_bind_front != 201907L +# error "__cpp_lib_bind_front should have the value 201907L in c++2b" # endif # if !defined(_LIBCPP_VERSION) diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp @@ -2268,17 +2268,11 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_bind_front -# error "__cpp_lib_bind_front should be defined in c++20" -# endif -# if __cpp_lib_bind_front != 201907L -# error "__cpp_lib_bind_front should have the value 201907L in c++20" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_bind_front -# error "__cpp_lib_bind_front should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_bind_front +# error "__cpp_lib_bind_front should be defined in c++20" +# endif +# if __cpp_lib_bind_front != 201907L +# error "__cpp_lib_bind_front should have the value 201907L in c++20" # endif # if !defined(_LIBCPP_VERSION) @@ -3487,17 +3481,11 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_bind_front -# error "__cpp_lib_bind_front should be defined in c++2b" -# endif -# if __cpp_lib_bind_front != 201907L -# error "__cpp_lib_bind_front should have the value 201907L in c++2b" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_bind_front -# error "__cpp_lib_bind_front should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_bind_front +# error "__cpp_lib_bind_front should be defined in c++2b" +# endif +# if __cpp_lib_bind_front != 201907L +# error "__cpp_lib_bind_front should have the value 201907L in c++2b" # endif # if !defined(_LIBCPP_VERSION) diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/pointer.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/pointer.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/pointer.pass.cpp @@ -29,6 +29,7 @@ void test(const S& s, const typename S::value_type* str, int x) { + LIBCPP_ASSERT_NOEXCEPT(s.compare(str)); assert(sign(s.compare(str)) == sign(x)); } diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp @@ -29,6 +29,7 @@ void test(const S& s, const S& str, int x) { + LIBCPP_ASSERT_NOEXCEPT(s.compare(str)); assert(sign(s.compare(str)) == sign(x)); } diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/string_view.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/string_view.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/string_view.pass.cpp @@ -29,6 +29,7 @@ void test(const S& s, SV sv, int x) { + LIBCPP_ASSERT_NOEXCEPT(s.compare(sv)); assert(sign(s.compare(sv)) == sign(x)); } diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/char_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/char_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/char_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, typename S::value_type c, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_not_of(c, pos)); assert(s.find_first_not_of(c, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); @@ -30,6 +31,7 @@ void test(const S& s, typename S::value_type c, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_not_of(c)); assert(s.find_first_not_of(c) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_not_of(str, pos)); assert(s.find_first_not_of(str, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_not_of(str, pos, n)); assert(s.find_first_not_of(str, pos, n) == x); if (x != S::npos) assert(pos <= x && x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_not_of(str, pos)); assert(s.find_first_not_of(str, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); @@ -29,6 +30,7 @@ void test(const S& s, const S& str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_not_of(str)); assert(s.find_first_not_of(str) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_view_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_view_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_view_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, SV sv, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_not_of(sv, pos)); assert(s.find_first_not_of(sv, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); @@ -29,6 +30,7 @@ void test(const S& s, SV sv, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_not_of(sv)); assert(s.find_first_not_of(sv) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/char_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/char_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/char_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, typename S::value_type c, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(c, pos)); assert(s.find_first_of(c, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); @@ -30,6 +31,7 @@ void test(const S& s, typename S::value_type c, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(c)); assert(s.find_first_of(c) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(str, pos)); assert(s.find_first_of(str, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); @@ -30,6 +31,7 @@ void test(const S& s, const typename S::value_type* str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(str)); assert(s.find_first_of(str) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(str, pos, n)); assert(s.find_first_of(str, pos, n) == x); if (x != S::npos) assert(pos <= x && x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(str, pos)); assert(s.find_first_of(str, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); @@ -29,6 +30,7 @@ void test(const S& s, const S& str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(str)); assert(s.find_first_of(str) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_view_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_view_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_view_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, SV sv, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(sv, pos)); assert(s.find_first_of(sv, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); @@ -29,6 +30,7 @@ void test(const S& s, SV sv, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(sv)); assert(s.find_first_of(sv) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/char_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/char_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/char_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, typename S::value_type c, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(c, pos)); assert(s.find_last_not_of(c, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); @@ -30,6 +31,7 @@ void test(const S& s, typename S::value_type c, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(c)); assert(s.find_last_not_of(c) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(str, pos)); assert(s.find_last_not_of(str, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); @@ -30,6 +31,7 @@ void test(const S& s, const typename S::value_type* str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(str)); assert(s.find_last_not_of(str) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(str, pos, n)); assert(s.find_last_not_of(str, pos, n) == x); if (x != S::npos) assert(x <= pos && x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(str, pos)); assert(s.find_last_not_of(str, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); @@ -29,6 +30,7 @@ void test(const S& s, const S& str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(str)); assert(s.find_last_not_of(str) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_view_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_view_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_view_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, SV sv, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(sv, pos)); assert(s.find_last_not_of(sv, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); @@ -29,6 +30,7 @@ void test(const S& s, SV sv, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(sv)); assert(s.find_last_not_of(sv) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/char_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/char_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/char_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, typename S::value_type c, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(c, pos)); assert(s.find_last_of(c, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); @@ -30,6 +31,7 @@ void test(const S& s, typename S::value_type c, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(c)); assert(s.find_last_of(c) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(str, pos)); assert(s.find_last_of(str, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); @@ -30,6 +31,7 @@ void test(const S& s, const typename S::value_type* str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(str)); assert(s.find_last_of(str) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(str, pos, n)); assert(s.find_last_of(str, pos, n) == x); if (x != S::npos) assert(x <= pos && x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(str, pos)); assert(s.find_last_of(str, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); @@ -29,6 +30,7 @@ void test(const S& s, const S& str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(str)); assert(s.find_last_of(str) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_view_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_view_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_view_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, SV sv, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(sv, pos)); assert(s.find_last_of(sv, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); @@ -29,6 +30,7 @@ void test(const S& s, SV sv, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(sv)); assert(s.find_last_of(sv) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/char_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find/char_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/char_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, typename S::value_type c, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(c, pos)); assert(s.find(c, pos) == x); if (x != S::npos) assert(pos <= x && x + 1 <= s.size()); @@ -30,6 +31,7 @@ void test(const S& s, typename S::value_type c, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(c)); assert(s.find(c) == x); if (x != S::npos) assert(0 <= x && x + 1 <= s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(str, pos)); assert(s.find(str, pos) == x); if (x != S::npos) { @@ -33,6 +34,7 @@ void test(const S& s, const typename S::value_type* str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(str)); assert(s.find(str) == x); if (x != S::npos) { diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(str, pos, n)); assert(s.find(str, pos, n) == x); if (x != S::npos) assert(pos <= x && x + n <= s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(str, pos)); assert(s.find(str, pos) == x); if (x != S::npos) assert(pos <= x && x + str.size() <= s.size()); @@ -29,6 +30,7 @@ void test(const S& s, const S& str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(str)); assert(s.find(str) == x); if (x != S::npos) assert(0 <= x && x + str.size() <= s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_view_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_view_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_view_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, SV sv, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(sv, pos)); assert(s.find(sv, pos) == x); if (x != S::npos) assert(pos <= x && x + sv.size() <= s.size()); @@ -29,6 +30,7 @@ void test(const S& s, SV sv, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(sv)); assert(s.find(sv) == x); if (x != S::npos) assert(0 <= x && x + sv.size() <= s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/char_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/char_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/char_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, typename S::value_type c, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(c, pos)); assert(s.rfind(c, pos) == x); if (x != S::npos) assert(x <= pos && x + 1 <= s.size()); @@ -30,6 +31,7 @@ void test(const S& s, typename S::value_type c, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(c)); assert(s.rfind(c) == x); if (x != S::npos) assert(x + 1 <= s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(str, pos)); assert(s.rfind(str, pos) == x); if (x != S::npos) { @@ -33,6 +34,7 @@ void test(const S& s, const typename S::value_type* str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(str)); assert(s.rfind(str) == x); if (x != S::npos) { diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(str, pos, n)); assert(s.rfind(str, pos, n) == x); if (x != S::npos) assert(x <= pos && x + n <= s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(str, pos)); assert(s.rfind(str, pos) == x); if (x != S::npos) assert(x <= pos && x + str.size() <= s.size()); @@ -29,6 +30,7 @@ void test(const S& s, const S& str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(str)); assert(s.rfind(str) == x); if (x != S::npos) assert(0 <= x && x + str.size() <= s.size()); diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_view_size.pass.cpp --- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_view_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_view_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, SV sv, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(sv, pos)); assert(s.rfind(sv, pos) == x); if (x != S::npos) assert(x <= pos && x + sv.size() <= s.size()); @@ -29,6 +30,7 @@ void test(const S& s, SV sv, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(sv)); assert(s.rfind(sv) == x); if (x != S::npos) assert(0 <= x && x + sv.size() <= s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_char_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_char_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_char_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_char_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, typename S::value_type c, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(c, pos)); assert(s.find(c, pos) == x); if (x != S::npos) assert(pos <= x && x + 1 <= s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_char_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_char_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_char_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_char_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, typename S::value_type c, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_not_of(c, pos)); assert(s.find_first_not_of(c, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); @@ -30,6 +31,7 @@ void test(const S& s, typename S::value_type c, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_not_of(c)); assert(s.find_first_not_of(c) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_pointer_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_pointer_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_pointer_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_pointer_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_not_of(str, pos)); assert(s.find_first_not_of(str, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_pointer_size_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_pointer_size_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_pointer_size_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_pointer_size_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_not_of(str, pos, n)); assert(s.find_first_not_of(str, pos, n) == x); if (x != S::npos) assert(pos <= x && x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_string_view_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_string_view_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_string_view_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_first_not_of_string_view_size.pass.cpp @@ -19,6 +19,7 @@ void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_not_of(str, pos)); assert(s.find_first_not_of(str, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_first_of_char_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_first_of_char_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_first_of_char_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_first_of_char_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, typename S::value_type c, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(c, pos)); assert(s.find_first_of(c, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_first_of_pointer_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_first_of_pointer_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_first_of_pointer_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_first_of_pointer_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(str, pos)); assert(s.find_first_of(str, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); @@ -30,6 +31,7 @@ void test(const S& s, const typename S::value_type* str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(str)); assert(s.find_first_of(str) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_first_of_pointer_size_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_first_of_pointer_size_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_first_of_pointer_size_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_first_of_pointer_size_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(str, pos, n)); assert(s.find_first_of(str, pos, n) == x); if (x != S::npos) assert(pos <= x && x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_first_of_string_view_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_first_of_string_view_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_first_of_string_view_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_first_of_string_view_size.pass.cpp @@ -19,6 +19,7 @@ void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(str, pos)); assert(s.find_first_of(str, pos) == x); if (x != S::npos) assert(pos <= x && x < s.size()); @@ -28,6 +29,7 @@ void test(const S& s, const S& str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_first_of(str)); assert(s.find_first_of(str) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_char_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_char_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_char_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_char_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, typename S::value_type c, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(c, pos)); assert(s.find_last_not_of(c, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); @@ -30,6 +31,7 @@ void test(const S& s, typename S::value_type c, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(c)); assert(s.find_last_not_of(c) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_pointer_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_pointer_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_pointer_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_pointer_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(str, pos)); assert(s.find_last_not_of(str, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_pointer_size_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_pointer_size_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_pointer_size_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_pointer_size_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(str, pos, n)); assert(s.find_last_not_of(str, pos, n) == x); if (x != S::npos) assert(x <= pos && x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_string_view_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_string_view_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_string_view_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_last_not_of_string_view_size.pass.cpp @@ -19,6 +19,7 @@ void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(str, pos)); assert(s.find_last_not_of(str, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); @@ -28,6 +29,7 @@ void test(const S& s, const S& str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_not_of(str)); assert(s.find_last_not_of(str) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_last_of_char_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_last_of_char_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_last_of_char_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_last_of_char_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, typename S::value_type c, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(c, pos)); assert(s.find_last_of(c, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); @@ -30,6 +31,7 @@ void test(const S& s, typename S::value_type c, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(c)); assert(s.find_last_of(c) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_last_of_pointer_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_last_of_pointer_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_last_of_pointer_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_last_of_pointer_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(str, pos)); assert(s.find_last_of(str, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); @@ -30,6 +31,7 @@ void test(const S& s, const typename S::value_type* str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(str)); assert(s.find_last_of(str) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_last_of_pointer_size_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_last_of_pointer_size_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_last_of_pointer_size_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_last_of_pointer_size_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(str, pos, n)); assert(s.find_last_of(str, pos, n) == x); if (x != S::npos) assert(x <= pos && x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_last_of_string_view_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_last_of_string_view_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_last_of_string_view_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_last_of_string_view_size.pass.cpp @@ -19,6 +19,7 @@ void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(str, pos)); assert(s.find_last_of(str, pos) == x); if (x != S::npos) assert(x <= pos && x < s.size()); @@ -28,6 +29,7 @@ void test(const S& s, const S& str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find_last_of(str)); assert(s.find_last_of(str) == x); if (x != S::npos) assert(x < s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_pointer_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_pointer_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_pointer_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_pointer_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(str, pos)); assert(s.find(str, pos) == x); if (x != S::npos) { @@ -33,6 +34,7 @@ void test(const S& s, const typename S::value_type* str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(str)); assert(s.find(str) == x); if (x != S::npos) { diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_pointer_size_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_pointer_size_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_pointer_size_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_pointer_size_size.pass.cpp @@ -21,6 +21,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(str, pos, n)); assert(s.find(str, pos, n) == x); if (x != S::npos) assert(pos <= x && x + n <= s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/find_string_view_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/find_string_view_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/find_string_view_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/find_string_view_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(str, pos)); assert(s.find(str, pos) == x); if (x != S::npos) assert(pos <= x && x + str.size() <= s.size()); @@ -29,6 +30,7 @@ void test(const S& s, const S& str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.find(str)); assert(s.find(str) == x); if (x != S::npos) assert(0 <= x && x + str.size() <= s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/rfind_char_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/rfind_char_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/rfind_char_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/rfind_char_size.pass.cpp @@ -20,6 +20,7 @@ test(const S& s, typename S::value_type c, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(c, pos)); assert(s.rfind(c, pos) == x); if (x != S::npos) assert(x <= pos && x + 1 <= s.size()); @@ -29,6 +30,7 @@ void test(const S& s, typename S::value_type c, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(c)); assert(s.rfind(c) == x); if (x != S::npos) assert(x + 1 <= s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/rfind_pointer_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/rfind_pointer_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/rfind_pointer_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/rfind_pointer_size.pass.cpp @@ -20,6 +20,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(str, pos)); assert(s.rfind(str, pos) == x); if (x != S::npos) { @@ -32,6 +33,7 @@ void test(const S& s, const typename S::value_type* str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(str)); assert(s.rfind(str) == x); if (x != S::npos) { diff --git a/libcxx/test/std/strings/string.view/string.view.find/rfind_pointer_size_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/rfind_pointer_size_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/rfind_pointer_size_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/rfind_pointer_size_size.pass.cpp @@ -20,6 +20,7 @@ test(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(str, pos, n)); assert(s.rfind(str, pos, n) == x); if (x != S::npos) assert(x <= pos && x + n <= s.size()); diff --git a/libcxx/test/std/strings/string.view/string.view.find/rfind_string_view_size.pass.cpp b/libcxx/test/std/strings/string.view/string.view.find/rfind_string_view_size.pass.cpp --- a/libcxx/test/std/strings/string.view/string.view.find/rfind_string_view_size.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.find/rfind_string_view_size.pass.cpp @@ -20,6 +20,7 @@ void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(str, pos)); assert(s.rfind(str, pos) == x); if (x != S::npos) assert(x <= pos && x + str.size() <= s.size()); @@ -29,6 +30,7 @@ void test(const S& s, const S& str, typename S::size_type x) { + LIBCPP_ASSERT_NOEXCEPT(s.rfind(str)); assert(s.rfind(str) == x); if (x != S::npos) assert(0 <= x && x + str.size() <= s.size()); diff --git a/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.pass.cpp b/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.pass.cpp @@ -0,0 +1,301 @@ +//===----------------------------------------------------------------------===// +// +// 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++98, c++03, c++11, c++14, c++17 + +// functional + +// template constexpr unspecified bind_front(F&&, Args&&...); + +#include + +#include "callable_types.h" +#include "test_macros.h" + +constexpr int add(int a, int b) { return a + b; } + +constexpr int long_test(int a, int b, int c, int d, int e, int f) { + return a + b + c + d + e + f; +} + +struct Foo { + int a; + int b; +}; + +struct FooCall { + constexpr Foo operator()(int a, int b) { return Foo{a, b}; } +}; + +struct S { + constexpr bool operator()(int a) { return a == 1; } +}; + +struct CopyMoveInfo { + enum { none, copy, move } copy_kind; + + constexpr CopyMoveInfo() : copy_kind(none) {} + constexpr CopyMoveInfo(CopyMoveInfo const&) : copy_kind(copy) {} + constexpr CopyMoveInfo(CopyMoveInfo&&) : copy_kind(move) {} +}; + +constexpr bool wasCopied(CopyMoveInfo info) { + return info.copy_kind == CopyMoveInfo::copy; +} +constexpr bool wasMoved(CopyMoveInfo info) { + return info.copy_kind == CopyMoveInfo::move; +} + +constexpr void basic_tests() { + int n = 2; + int m = 1; + + auto a = std::bind_front(add, m, n); + assert(a() == 3); + + auto b = std::bind_front(long_test, m, n, m, m, m, m); + assert(b() == 7); + + auto c = std::bind_front(long_test, n, m); + assert(c(1, 1, 1, 1) == 7); + + auto d = std::bind_front(S{}, m); + assert(d()); + + auto f = std::bind_front(add, n); + assert(f(3) == 5); + + auto g = std::bind_front(add, n, 1); + assert(g() == 3); + + auto h = std::bind_front(long_test, 1, 1, 1); + assert(h(2, 2, 2) == 9); + + // Make sure the arg is passed by value. + auto i = std::bind_front(add, n, 1); + n = 100; + assert(i() == 3); + + CopyMoveInfo info; + auto copied = std::bind_front(wasCopied, info); + assert(copied()); + + auto moved = std::bind_front(wasMoved, info); + assert(std::move(moved)()); +} + +struct variadic_fn { + template + constexpr int operator()(Args&&... args) { + return sizeof...(args); + } +}; + +constexpr void test_variadic() { + variadic_fn value; + auto fn = std::bind_front(value, 0, 0, 0); + assert(fn(0, 0, 0) == 6); +} + +struct mutable_callable { + bool should_call_const; + + constexpr bool operator()(int, int) { + assert(!should_call_const); + return true; + } + constexpr bool operator()(int, int) const { + assert(should_call_const); + return true; + } +}; + +constexpr void test_mutable() { + const mutable_callable v1{true}; + const auto fn1 = std::bind_front(v1, 0); + assert(fn1(0)); + + mutable_callable v2{false}; + auto fn2 = std::bind_front(v2, 0); + assert(fn2(0)); +}; + +struct call_member { + constexpr bool member(int, int) { return true; } +}; + +constexpr void test_call_member() { + call_member value; + auto fn = std::bind_front(&call_member::member, value, 0); + assert(fn(0)); +} + +struct no_const_lvalue { + constexpr void operator()(int) && {}; +}; + +constexpr auto make_no_const_lvalue(int x) { + // This is to test that bind_front works when something like the following would not: + // return [nc = no_const_lvalue{}, x] { return nc(x); }; + // Above would not work because it would look for a () const & overload. + return std::bind_front(no_const_lvalue{}, x); +} + +constexpr void test_no_const_lvalue() { make_no_const_lvalue(1)(); } + +constexpr void constructor_tests() { + { + MoveOnlyCallable value(true); + using RetT = decltype(std::bind_front(std::move(value), 1)); + + static_assert(std::is_move_constructible::value); + static_assert(!std::is_copy_constructible::value); + static_assert(!std::is_move_assignable::value); + static_assert(!std::is_copy_assignable::value); + + auto ret = std::bind_front(std::move(value), 1); + assert(ret()); + assert(ret(1, 2, 3)); + + auto ret1 = std::move(ret); + assert(!ret()); + assert(ret1()); + assert(ret1(1, 2, 3)); + } + { + CopyCallable value(true); + using RetT = decltype(std::bind_front(value, 1)); + + static_assert(std::is_move_constructible::value); + static_assert(std::is_copy_constructible::value); + static_assert(!std::is_move_assignable::value); + static_assert(!std::is_copy_assignable::value); + + auto ret = std::bind_front(value, 1); + assert(ret()); + assert(ret(1, 2, 3)); + + auto ret1 = std::move(ret); + assert(ret1()); + assert(ret1(1, 2, 3)); + + auto ret2 = std::bind_front(std::move(value), 1); + assert(!ret()); + assert(ret2()); + assert(ret2(1, 2, 3)); + } + { + CopyAssignableWrapper value(true); + using RetT = decltype(std::bind_front(value, 1)); + + static_assert(std::is_move_constructible::value); + static_assert(std::is_copy_constructible::value); + static_assert(std::is_move_assignable::value); + static_assert(std::is_copy_assignable::value); + } + { + MoveAssignableWrapper value(true); + using RetT = decltype(std::bind_front(std::move(value), 1)); + + static_assert(std::is_move_constructible::value); + static_assert(!std::is_copy_constructible::value); + static_assert(std::is_move_assignable::value); + static_assert(!std::is_copy_assignable::value); + } +} + +template +constexpr void test_return(F&& value, Args&&... args) { + auto ret = + std::bind_front(std::forward(value), std::forward(args)...); + static_assert(std::is_same::value); +} + +constexpr void test_return_types() { + test_return(FooCall{}, 1, 2); + test_return(S{}, 1); + test_return(add, 2, 2); +} + +constexpr void test_arg_count() { + using T = decltype(std::bind_front(add, 1)); + static_assert(!std::is_invocable::value); + static_assert(std::is_invocable::value); +} + +template +struct is_bind_front_invokable { + template + static auto test(int) + -> decltype((void)std::bind_front(std::declval()...), + std::true_type()); + + template + static std::false_type test(...); + + static constexpr bool value = decltype(test(0))::value; +}; + +struct NotCopyMove { + NotCopyMove() = delete; + NotCopyMove(const NotCopyMove&) = delete; + NotCopyMove(NotCopyMove&&) = delete; + void operator()() {} +}; + +struct NonConstCopyConstructible { + explicit NonConstCopyConstructible() {} + NonConstCopyConstructible(NonConstCopyConstructible&) {} +}; + +struct MoveConstructible { + explicit MoveConstructible() {} + MoveConstructible(MoveConstructible&&) {} +}; + +constexpr void test_invocability() { + static_assert(!std::is_constructible_v); + static_assert(!std::is_move_constructible_v); + static_assert(!is_bind_front_invokable::value); + static_assert(!is_bind_front_invokable::value); + + static_assert( + !std::is_constructible_v); + static_assert(std::is_move_constructible_v); + static_assert(is_bind_front_invokable::value); + static_assert( + !is_bind_front_invokable::value); + + static_assert(std::is_constructible_v); + static_assert(!std::is_move_constructible_v); + static_assert( + !is_bind_front_invokable::value); + static_assert( + !is_bind_front_invokable::value); +} + +constexpr bool test() { + basic_tests(); + constructor_tests(); + test_return_types(); + test_arg_count(); + test_variadic(); + test_mutable(); + test_call_member(); + test_no_const_lvalue(); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.verify.cpp b/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.verify.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// 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++98, c++03, c++11, c++14, c++17 + +// functional + +// template constexpr unspecified bind_front(F&&, Args&&...); + +#include + +#include "test_macros.h" + +constexpr int pass(const int n) { return n; } + +int simple(int n) { return n; } + +template +T do_nothing(T t) { return t; } + +struct NotMoveConst +{ + NotMoveConst(NotMoveConst &&) = delete; + NotMoveConst(NotMoveConst const&) = delete; + + NotMoveConst(int) { } +}; + +void testNotMoveConst(NotMoveConst) { } + +int main(int, char**) +{ + int n = 1; + const int c = 1; + + auto p = std::bind_front(pass, c); + static_assert(p() == 1); // expected-error {{static_assert expression is not an integral constant expression}} + + auto d = std::bind_front(do_nothing, n); // expected-error {{no matching function for call to 'bind_front'}} + + auto t = std::bind_front(testNotMoveConst, NotMoveConst(0)); // expected-error {{no matching function for call to 'bind_front'}} + + return 0; +} diff --git a/libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp b/libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp --- a/libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp @@ -17,178 +17,7 @@ #include "test_macros.h" #include "type_id.h" - - -/////////////////////////////////////////////////////////////////////////////// -// CALLABLE TEST TYPES -/////////////////////////////////////////////////////////////////////////////// - -constexpr bool returns_true() { return true; } - -template -struct MoveOnlyCallable { - MoveOnlyCallable(MoveOnlyCallable const&) = delete; - constexpr MoveOnlyCallable(MoveOnlyCallable&& other) - : value(other.value) - { other.value = !other.value; } - - template - constexpr Ret operator()(Args&&...) { return Ret{value}; } - - constexpr explicit MoveOnlyCallable(bool x) : value(x) {} - Ret value; -}; - -template -struct CopyCallable { - constexpr CopyCallable(CopyCallable const& other) - : value(other.value) {} - - constexpr CopyCallable(CopyCallable&& other) - : value(other.value) { other.value = !other.value; } - - template - constexpr Ret operator()(Args&&...) { return Ret{value}; } - - constexpr explicit CopyCallable(bool x) : value(x) {} - Ret value; -}; - - -template -struct ConstCallable { - constexpr ConstCallable(ConstCallable const& other) - : value(other.value) {} - - constexpr ConstCallable(ConstCallable&& other) - : value(other.value) { other.value = !other.value; } - - template - constexpr Ret operator()(Args&&...) const { return Ret{value}; } - - constexpr explicit ConstCallable(bool x) : value(x) {} - Ret value; -}; - - - -template -struct NoExceptCallable { - constexpr NoExceptCallable(NoExceptCallable const& other) - : value(other.value) {} - - template - constexpr Ret operator()(Args&&...) noexcept { return Ret{value}; } - - template - constexpr Ret operator()(Args&&...) const noexcept { return Ret{value}; } - - constexpr explicit NoExceptCallable(bool x) : value(x) {} - Ret value; -}; - -struct CopyAssignableWrapper { - constexpr CopyAssignableWrapper(CopyAssignableWrapper const&) = default; - constexpr CopyAssignableWrapper(CopyAssignableWrapper&&) = default; - constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default; - constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default; - - template - constexpr bool operator()(Args&&...) { return value; } - - constexpr explicit CopyAssignableWrapper(bool x) : value(x) {} - bool value; -}; - - -struct MoveAssignableWrapper { - constexpr MoveAssignableWrapper(MoveAssignableWrapper const&) = delete; - constexpr MoveAssignableWrapper(MoveAssignableWrapper&&) = default; - constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete; - constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default; - - template - constexpr bool operator()(Args&&...) { return value; } - - constexpr explicit MoveAssignableWrapper(bool x) : value(x) {} - bool value; -}; - -struct MemFunCallable { - constexpr explicit MemFunCallable(bool x) : value(x) {} - - constexpr bool return_value() const { return value; } - constexpr bool return_value_nc() { return value; } - bool value; -}; - -enum CallType : unsigned { - CT_None, - CT_NonConst = 1, - CT_Const = 2, - CT_LValue = 4, - CT_RValue = 8 -}; - -inline constexpr CallType operator|(CallType LHS, CallType RHS) { - return static_cast(static_cast(LHS) | static_cast(RHS)); -} - -struct ForwardingCallObject { - struct State { - CallType last_call_type = CT_None; - TypeID const& (*last_call_args)() = nullptr; - - template - constexpr void set_call(CallType type) { - assert(last_call_type == CT_None); - assert(last_call_args == nullptr); - last_call_type = type; - last_call_args = &makeArgumentID; - } - - template - constexpr bool check_call(CallType type) { - bool result = - last_call_type == type - && last_call_args - && *last_call_args == &makeArgumentID; - last_call_type = CT_None; - last_call_args = nullptr; - return result; - } - }; - - State *st_; - - explicit constexpr ForwardingCallObject(State& st) : st_(&st) {} - - template - constexpr bool operator()(Args&&...) & { - st_->set_call(CT_NonConst | CT_LValue); - return true; - } - - template - constexpr bool operator()(Args&&...) const & { - st_->set_call(CT_Const | CT_LValue); - return true; - } - - // Don't allow the call operator to be invoked as an rvalue. - template - constexpr bool operator()(Args&&...) && { - st_->set_call(CT_NonConst | CT_RValue); - return true; - } - - template - constexpr bool operator()(Args&&...) const && { - st_->set_call(CT_Const | CT_RValue); - return true; - } -}; - +#include "callable_types.h" /////////////////////////////////////////////////////////////////////////////// // BOOL TEST TYPES @@ -298,6 +127,10 @@ assert(ret() == false); assert(ret2() == true); assert(ret2("abc") == true); + // initialize not_fn with rvalue + auto ret3 = std::not_fn(std::move(value)); + assert(ret(0) == false); + assert(ret3(0) == true); } { using T = CopyAssignableWrapper; @@ -306,17 +139,10 @@ using RetT = decltype(std::not_fn(value)); static_assert(std::is_move_constructible::value, ""); static_assert(std::is_copy_constructible::value, ""); - LIBCPP_STATIC_ASSERT(std::is_move_assignable::value, ""); - LIBCPP_STATIC_ASSERT(std::is_copy_assignable::value, ""); auto ret = std::not_fn(value); assert(ret() == false); auto ret2 = std::not_fn(value2); assert(ret2() == true); -#if defined(_LIBCPP_VERSION) - ret = ret2; - assert(ret() == true); - assert(ret2() == true); -#endif // _LIBCPP_VERSION } { using T = MoveAssignableWrapper; @@ -325,16 +151,11 @@ using RetT = decltype(std::not_fn(std::move(value))); static_assert(std::is_move_constructible::value, ""); static_assert(!std::is_copy_constructible::value, ""); - LIBCPP_STATIC_ASSERT(std::is_move_assignable::value, ""); static_assert(!std::is_copy_assignable::value, ""); auto ret = std::not_fn(std::move(value)); assert(ret() == false); auto ret2 = std::not_fn(std::move(value2)); assert(ret2() == true); -#if defined(_LIBCPP_VERSION) - ret = std::move(ret2); - assert(ret() == true); -#endif // _LIBCPP_VERSION } return true; } diff --git a/libcxx/test/support/callable_types.h b/libcxx/test/support/callable_types.h new file mode 100644 --- /dev/null +++ b/libcxx/test/support/callable_types.h @@ -0,0 +1,186 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_CALLABLE_TYPES_H +#define TEST_CALLABLE_TYPES_H + +#include "test_macros.h" +#include "type_id.h" + +/////////////////////////////////////////////////////////////////////////////// +// CALLABLE TEST TYPES +/////////////////////////////////////////////////////////////////////////////// + +constexpr bool returns_true() { return true; } + +template +struct MoveOnlyCallable { + MoveOnlyCallable(MoveOnlyCallable const&) = delete; + constexpr MoveOnlyCallable(MoveOnlyCallable&& other) + : value(other.value) + { other.value = !other.value; } + + template + constexpr Ret operator()(Args&&...) { return Ret{value}; } + + constexpr explicit MoveOnlyCallable(bool x) : value(x) {} + Ret value; +}; + +template +struct CopyCallable { + constexpr CopyCallable(CopyCallable const& other) + : value(other.value) {} + + constexpr CopyCallable(CopyCallable&& other) + : value(other.value) { other.value = !other.value; } + + template + constexpr Ret operator()(Args&&...) { return Ret{value}; } + + constexpr explicit CopyCallable(bool x) : value(x) {} + Ret value; +}; + + +template +struct ConstCallable { + constexpr ConstCallable(ConstCallable const& other) + : value(other.value) {} + + constexpr ConstCallable(ConstCallable&& other) + : value(other.value) { other.value = !other.value; } + + template + constexpr Ret operator()(Args&&...) const { return Ret{value}; } + + constexpr explicit ConstCallable(bool x) : value(x) {} + Ret value; +}; + + + +template +struct NoExceptCallable { + constexpr NoExceptCallable(NoExceptCallable const& other) + : value(other.value) {} + + template + constexpr Ret operator()(Args&&...) noexcept { return Ret{value}; } + + template + constexpr Ret operator()(Args&&...) const noexcept { return Ret{value}; } + + constexpr explicit NoExceptCallable(bool x) : value(x) {} + Ret value; +}; + +struct CopyAssignableWrapper { + constexpr CopyAssignableWrapper(CopyAssignableWrapper const&) = default; + constexpr CopyAssignableWrapper(CopyAssignableWrapper&&) = default; + constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default; + constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default; + + template + constexpr bool operator()(Args&&...) { return value; } + + constexpr explicit CopyAssignableWrapper(bool x) : value(x) {} + bool value; +}; + + +struct MoveAssignableWrapper { + constexpr MoveAssignableWrapper(MoveAssignableWrapper const&) = delete; + constexpr MoveAssignableWrapper(MoveAssignableWrapper&&) = default; + constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete; + constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default; + + template + constexpr bool operator()(Args&&...) { return value; } + + constexpr explicit MoveAssignableWrapper(bool x) : value(x) {} + bool value; +}; + +struct MemFunCallable { + constexpr explicit MemFunCallable(bool x) : value(x) {} + + constexpr bool return_value() const { return value; } + constexpr bool return_value_nc() { return value; } + bool value; +}; + +enum CallType : unsigned { + CT_None, + CT_NonConst = 1, + CT_Const = 2, + CT_LValue = 4, + CT_RValue = 8 +}; + +inline constexpr CallType operator|(CallType LHS, CallType RHS) { + return static_cast(static_cast(LHS) | static_cast(RHS)); +} + +struct ForwardingCallObject { + struct State { + CallType last_call_type = CT_None; + TypeID const& (*last_call_args)() = nullptr; + + template + constexpr void set_call(CallType type) { + assert(last_call_type == CT_None); + assert(last_call_args == nullptr); + last_call_type = type; + last_call_args = &makeArgumentID; + } + + template + constexpr bool check_call(CallType type) { + bool result = + last_call_type == type + && last_call_args + && *last_call_args == &makeArgumentID; + last_call_type = CT_None; + last_call_args = nullptr; + return result; + } + }; + + State *st_; + + explicit constexpr ForwardingCallObject(State& st) : st_(&st) {} + + template + constexpr bool operator()(Args&&...) & { + st_->set_call(CT_NonConst | CT_LValue); + return true; + } + + template + constexpr bool operator()(Args&&...) const & { + st_->set_call(CT_Const | CT_LValue); + return true; + } + + // Don't allow the call operator to be invoked as an rvalue. + template + constexpr bool operator()(Args&&...) && { + st_->set_call(CT_NonConst | CT_RValue); + return true; + } + + template + constexpr bool operator()(Args&&...) const && { + st_->set_call(CT_Const | CT_RValue); + return true; + } +}; + + +#endif // TEST_CALLABLE_TYPES_H \ No newline at end of file diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -123,7 +123,6 @@ "name": "__cpp_lib_bind_front", "values": { "c++20": 201907 }, "headers": ["functional"], - "unimplemented": True, }, { "name": "__cpp_lib_bit_cast", "values": { "c++20": 201806 },