These _S_noexcept() functions are only used in noexcept-specifiers and never need to be called at runtime. They can be immediate functions, i.e. consteval.
libstdc++-v3/ChangeLog: * include/bits/iterator_concepts.h (_IterMove::_S_noexcept) (_IterSwap::_S_noexcept): Change constexpr to consteval. * include/bits/ranges_base.h (_Begin::_S_noexcept) (_End::_S_noexcept, _RBegin::_S_noexcept, _REnd::_S_noexcept) (_Size::_S_noexcept, _Empty::_S_noexcept, _Data::_S_noexcept): Likewise. * include/std/concepts (_Swap::_S_noexcept): Likewise. --- Tested powerpc64-linux. libstdc++-v3/include/bits/iterator_concepts.h | 4 ++-- libstdc++-v3/include/bits/ranges_base.h | 14 +++++++------- libstdc++-v3/include/std/concepts | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h index 979039e7da53..fd91b22d75a5 100644 --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -141,21 +141,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { // Instead of decltype(std::move(*E)) we define the type as the // return type of std::move, i.e. remove_reference_t<iter_ref>&&. // N.B. the use of decltype(declval<X>()) instead of just X&& is // needed for function reference types, see PR libstdc++/119469. using type = decltype(std::declval<remove_reference_t<__iter_ref_t<_Tp>>>()); }; template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (__adl_imove<_Tp>) return noexcept(iter_move(std::declval<_Tp>())); else return noexcept(*std::declval<_Tp>()); } public: // The result type of iter_move(std::declval<_Tp>()) @@ -877,21 +877,21 @@ namespace ranges { iter_value_t<_Xp> __old_value(iter_move(__x)); *__x = iter_move(__y); return __old_value; } struct _IterSwap { private: template<typename _Tp, typename _Up> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (__adl_iswap<_Tp, _Up>) return noexcept(iter_swap(std::declval<_Tp>(), std::declval<_Up>())); else if constexpr (indirectly_readable<_Tp> && indirectly_readable<_Up> && swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>) return noexcept(ranges::swap(*std::declval<_Tp>(), *std::declval<_Up>())); diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index c1a9f6a90009..1c4bf432c8f4 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -99,21 +99,21 @@ namespace ranges // Namespace for helpers for the <ranges> customization points. namespace __access { using std::ranges::__detail::__maybe_borrowed_range; using std::__detail::__range_iter_t; struct _Begin { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (is_array_v<remove_reference_t<_Tp>>) return true; else if constexpr (__member_begin<_Tp>) return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().begin())); else return noexcept(_GLIBCXX_AUTO_CAST(begin(std::declval<_Tp&>()))); } @@ -150,21 +150,21 @@ namespace ranges concept __adl_end = __class_or_enum<remove_reference_t<_Tp>> && requires(_Tp& __t) { { _GLIBCXX_AUTO_CAST(end(__t)) } -> sentinel_for<__range_iter_t<_Tp>>; }; struct _End { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>) return true; else if constexpr (__member_end<_Tp>) return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().end())); else return noexcept(_GLIBCXX_AUTO_CAST(end(std::declval<_Tp&>()))); } @@ -207,21 +207,21 @@ namespace ranges concept __reversable = requires(_Tp& __t) { { _Begin{}(__t) } -> bidirectional_iterator; { _End{}(__t) } -> same_as<decltype(_Begin{}(__t))>; }; struct _RBegin { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (__member_rbegin<_Tp>) return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().rbegin())); else if constexpr (__adl_rbegin<_Tp>) return noexcept(_GLIBCXX_AUTO_CAST(rbegin(std::declval<_Tp&>()))); else { if constexpr (noexcept(_End{}(std::declval<_Tp&>()))) { @@ -265,21 +265,21 @@ namespace ranges && requires(_Tp& __t) { { _GLIBCXX_AUTO_CAST(rend(__t)) } -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>; }; struct _REnd { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (__member_rend<_Tp>) return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().rend())); else if constexpr (__adl_rend<_Tp>) return noexcept(_GLIBCXX_AUTO_CAST(rend(std::declval<_Tp&>()))); else { if constexpr (noexcept(_Begin{}(std::declval<_Tp&>()))) { @@ -335,21 +335,21 @@ namespace ranges { _End{}(__t) } -> sized_sentinel_for<decltype(_Begin{}(__t))>; __detail::__to_unsigned_like(_End{}(__t) - _Begin{}(__t)); }; struct _Size { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>) return true; else if constexpr (__member_size<_Tp>) return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().size())); else if constexpr (__adl_size<_Tp>) return noexcept(_GLIBCXX_AUTO_CAST(size(std::declval<_Tp&>()))); else if constexpr (__sentinel_size<_Tp>) return noexcept(_End{}(std::declval<_Tp&>()) @@ -415,21 +415,21 @@ namespace ranges { _Begin{}(__t) } -> forward_iterator; bool(_Begin{}(__t) == _End{}(__t)); }; struct _Empty { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (__member_empty<_Tp>) return noexcept(bool(std::declval<_Tp&>().empty())); else if constexpr (__size0_empty<_Tp>) return noexcept(_Size{}(std::declval<_Tp&>()) == 0); else return noexcept(bool(_Begin{}(std::declval<_Tp&>()) == _End{}(std::declval<_Tp&>()))); } @@ -461,21 +461,21 @@ namespace ranges { _GLIBCXX_AUTO_CAST(__t.data()) } -> __pointer_to_object; }; template<typename _Tp> concept __begin_data = contiguous_iterator<__range_iter_t<_Tp>>; struct _Data { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (__member_data<_Tp>) return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().data())); else return noexcept(_Begin{}(std::declval<_Tp&>())); } public: template<__maybe_borrowed_range _Tp> diff --git a/libstdc++-v3/include/std/concepts b/libstdc++-v3/include/std/concepts index 5899f032434a..d9920a8f20a8 100644 --- a/libstdc++-v3/include/std/concepts +++ b/libstdc++-v3/include/std/concepts @@ -197,21 +197,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION = (std::__detail::__class_or_enum<remove_reference_t<_Tp>> || std::__detail::__class_or_enum<remove_reference_t<_Up>>) && requires(_Tp&& __t, _Up&& __u) { swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); }; struct _Swap { private: template<typename _Tp, typename _Up> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (__adl_swap<_Tp, _Up>) return noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())); else return is_nothrow_move_constructible_v<remove_reference_t<_Tp>> && is_nothrow_move_assignable_v<remove_reference_t<_Tp>>; } public: -- 2.51.0