11debfc3dSmrg// <utility> -*- C++ -*- 21debfc3dSmrg 3*8feb0f0bSmrg// Copyright (C) 2001-2020 Free Software Foundation, Inc. 41debfc3dSmrg// 51debfc3dSmrg// This file is part of the GNU ISO C++ Library. This library is free 61debfc3dSmrg// software; you can redistribute it and/or modify it under the 71debfc3dSmrg// terms of the GNU General Public License as published by the 81debfc3dSmrg// Free Software Foundation; either version 3, or (at your option) 91debfc3dSmrg// any later version. 101debfc3dSmrg 111debfc3dSmrg// This library is distributed in the hope that it will be useful, 121debfc3dSmrg// but WITHOUT ANY WARRANTY; without even the implied warranty of 131debfc3dSmrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141debfc3dSmrg// GNU General Public License for more details. 151debfc3dSmrg 161debfc3dSmrg// Under Section 7 of GPL version 3, you are granted additional 171debfc3dSmrg// permissions described in the GCC Runtime Library Exception, version 181debfc3dSmrg// 3.1, as published by the Free Software Foundation. 191debfc3dSmrg 201debfc3dSmrg// You should have received a copy of the GNU General Public License and 211debfc3dSmrg// a copy of the GCC Runtime Library Exception along with this program; 221debfc3dSmrg// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 231debfc3dSmrg// <http://www.gnu.org/licenses/>. 241debfc3dSmrg 251debfc3dSmrg/* 261debfc3dSmrg * 271debfc3dSmrg * Copyright (c) 1994 281debfc3dSmrg * Hewlett-Packard Company 291debfc3dSmrg * 301debfc3dSmrg * Permission to use, copy, modify, distribute and sell this software 311debfc3dSmrg * and its documentation for any purpose is hereby granted without fee, 321debfc3dSmrg * provided that the above copyright notice appear in all copies and 331debfc3dSmrg * that both that copyright notice and this permission notice appear 341debfc3dSmrg * in supporting documentation. Hewlett-Packard Company makes no 351debfc3dSmrg * representations about the suitability of this software for any 361debfc3dSmrg * purpose. It is provided "as is" without express or implied warranty. 371debfc3dSmrg * 381debfc3dSmrg * 391debfc3dSmrg * Copyright (c) 1996,1997 401debfc3dSmrg * Silicon Graphics Computer Systems, Inc. 411debfc3dSmrg * 421debfc3dSmrg * Permission to use, copy, modify, distribute and sell this software 431debfc3dSmrg * and its documentation for any purpose is hereby granted without fee, 441debfc3dSmrg * provided that the above copyright notice appear in all copies and 451debfc3dSmrg * that both that copyright notice and this permission notice appear 461debfc3dSmrg * in supporting documentation. Silicon Graphics makes no 471debfc3dSmrg * representations about the suitability of this software for any 481debfc3dSmrg * purpose. It is provided "as is" without express or implied warranty. 491debfc3dSmrg */ 501debfc3dSmrg 511debfc3dSmrg/** @file include/utility 521debfc3dSmrg * This is a Standard C++ Library header. 531debfc3dSmrg */ 541debfc3dSmrg 551debfc3dSmrg#ifndef _GLIBCXX_UTILITY 561debfc3dSmrg#define _GLIBCXX_UTILITY 1 571debfc3dSmrg 581debfc3dSmrg#pragma GCC system_header 591debfc3dSmrg 601debfc3dSmrg/** 611debfc3dSmrg * @defgroup utilities Utilities 621debfc3dSmrg * 631debfc3dSmrg * Components deemed generally useful. Includes pair, tuple, 641debfc3dSmrg * forward/move helpers, ratio, function object, metaprogramming and 651debfc3dSmrg * type traits, time, date, and memory functions. 661debfc3dSmrg */ 671debfc3dSmrg 681debfc3dSmrg#include <bits/c++config.h> 691debfc3dSmrg#include <bits/stl_relops.h> 701debfc3dSmrg#include <bits/stl_pair.h> 711debfc3dSmrg 721debfc3dSmrg#if __cplusplus >= 201103L 731debfc3dSmrg 741debfc3dSmrg#include <type_traits> 751debfc3dSmrg#include <bits/move.h> 761debfc3dSmrg#include <initializer_list> 771debfc3dSmrg 78*8feb0f0bSmrg#if __cplusplus > 201703L 79*8feb0f0bSmrg#include <ext/numeric_traits.h> 80*8feb0f0bSmrg#endif 81*8feb0f0bSmrg 821debfc3dSmrgnamespace std _GLIBCXX_VISIBILITY(default) 831debfc3dSmrg{ 841debfc3dSmrg_GLIBCXX_BEGIN_NAMESPACE_VERSION 851debfc3dSmrg 861debfc3dSmrg /// Finds the size of a given tuple type. 871debfc3dSmrg template<typename _Tp> 881debfc3dSmrg struct tuple_size; 891debfc3dSmrg 901debfc3dSmrg // _GLIBCXX_RESOLVE_LIB_DEFECTS 91a2dc1f3fSmrg // 2313. tuple_size should always derive from integral_constant<size_t, N> 921debfc3dSmrg // 2770. tuple_size<const T> specialization is not SFINAE compatible 931debfc3dSmrg 941debfc3dSmrg template<typename _Tp, 951debfc3dSmrg typename _Up = typename remove_cv<_Tp>::type, 961debfc3dSmrg typename = typename enable_if<is_same<_Tp, _Up>::value>::type, 971debfc3dSmrg size_t = tuple_size<_Tp>::value> 981debfc3dSmrg using __enable_if_has_tuple_size = _Tp; 991debfc3dSmrg 1001debfc3dSmrg template<typename _Tp> 1011debfc3dSmrg struct tuple_size<const __enable_if_has_tuple_size<_Tp>> 1021debfc3dSmrg : public tuple_size<_Tp> { }; 1031debfc3dSmrg 1041debfc3dSmrg template<typename _Tp> 1051debfc3dSmrg struct tuple_size<volatile __enable_if_has_tuple_size<_Tp>> 1061debfc3dSmrg : public tuple_size<_Tp> { }; 1071debfc3dSmrg 1081debfc3dSmrg template<typename _Tp> 1091debfc3dSmrg struct tuple_size<const volatile __enable_if_has_tuple_size<_Tp>> 1101debfc3dSmrg : public tuple_size<_Tp> { }; 1111debfc3dSmrg 1121debfc3dSmrg /// Gives the type of the ith element of a given tuple type. 1131debfc3dSmrg template<std::size_t __i, typename _Tp> 1141debfc3dSmrg struct tuple_element; 1151debfc3dSmrg 1161debfc3dSmrg // Duplicate of C++14's tuple_element_t for internal use in C++11 mode 1171debfc3dSmrg template<std::size_t __i, typename _Tp> 1181debfc3dSmrg using __tuple_element_t = typename tuple_element<__i, _Tp>::type; 1191debfc3dSmrg 1201debfc3dSmrg template<std::size_t __i, typename _Tp> 1211debfc3dSmrg struct tuple_element<__i, const _Tp> 1221debfc3dSmrg { 1231debfc3dSmrg typedef typename add_const<__tuple_element_t<__i, _Tp>>::type type; 1241debfc3dSmrg }; 1251debfc3dSmrg 1261debfc3dSmrg template<std::size_t __i, typename _Tp> 1271debfc3dSmrg struct tuple_element<__i, volatile _Tp> 1281debfc3dSmrg { 1291debfc3dSmrg typedef typename add_volatile<__tuple_element_t<__i, _Tp>>::type type; 1301debfc3dSmrg }; 1311debfc3dSmrg 1321debfc3dSmrg template<std::size_t __i, typename _Tp> 1331debfc3dSmrg struct tuple_element<__i, const volatile _Tp> 1341debfc3dSmrg { 1351debfc3dSmrg typedef typename add_cv<__tuple_element_t<__i, _Tp>>::type type; 1361debfc3dSmrg }; 1371debfc3dSmrg 138c0a68be4Smrg#if __cplusplus >= 201402L 139c0a68be4Smrg// The standard says this macro and alias template should be in <tuple> 140c0a68be4Smrg// but we define them here, to be available when the partial specializations 141c0a68be4Smrg// of tuple_element<pair<T,U>> and tuple_element<array<T,N>> are defined. 142c0a68be4Smrg#define __cpp_lib_tuple_element_t 201402L 1431debfc3dSmrg 1441debfc3dSmrg template<std::size_t __i, typename _Tp> 1451debfc3dSmrg using tuple_element_t = typename tuple_element<__i, _Tp>::type; 1461debfc3dSmrg#endif 1471debfc3dSmrg 1481debfc3dSmrg // Various functions which give std::pair a tuple-like interface. 1491debfc3dSmrg 1501debfc3dSmrg /// Partial specialization for std::pair 1511debfc3dSmrg template<typename _T1, typename _T2> 1521debfc3dSmrg struct __is_tuple_like_impl<std::pair<_T1, _T2>> : true_type 1531debfc3dSmrg { }; 1541debfc3dSmrg 1551debfc3dSmrg /// Partial specialization for std::pair 1561debfc3dSmrg template<class _Tp1, class _Tp2> 1571debfc3dSmrg struct tuple_size<std::pair<_Tp1, _Tp2>> 1581debfc3dSmrg : public integral_constant<std::size_t, 2> { }; 1591debfc3dSmrg 1601debfc3dSmrg /// Partial specialization for std::pair 1611debfc3dSmrg template<class _Tp1, class _Tp2> 1621debfc3dSmrg struct tuple_element<0, std::pair<_Tp1, _Tp2>> 1631debfc3dSmrg { typedef _Tp1 type; }; 1641debfc3dSmrg 1651debfc3dSmrg /// Partial specialization for std::pair 1661debfc3dSmrg template<class _Tp1, class _Tp2> 1671debfc3dSmrg struct tuple_element<1, std::pair<_Tp1, _Tp2>> 1681debfc3dSmrg { typedef _Tp2 type; }; 1691debfc3dSmrg 1701debfc3dSmrg template<std::size_t _Int> 1711debfc3dSmrg struct __pair_get; 1721debfc3dSmrg 1731debfc3dSmrg template<> 1741debfc3dSmrg struct __pair_get<0> 1751debfc3dSmrg { 1761debfc3dSmrg template<typename _Tp1, typename _Tp2> 1771debfc3dSmrg static constexpr _Tp1& 1781debfc3dSmrg __get(std::pair<_Tp1, _Tp2>& __pair) noexcept 1791debfc3dSmrg { return __pair.first; } 1801debfc3dSmrg 1811debfc3dSmrg template<typename _Tp1, typename _Tp2> 1821debfc3dSmrg static constexpr _Tp1&& 1831debfc3dSmrg __move_get(std::pair<_Tp1, _Tp2>&& __pair) noexcept 1841debfc3dSmrg { return std::forward<_Tp1>(__pair.first); } 1851debfc3dSmrg 1861debfc3dSmrg template<typename _Tp1, typename _Tp2> 1871debfc3dSmrg static constexpr const _Tp1& 1881debfc3dSmrg __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept 1891debfc3dSmrg { return __pair.first; } 190a2dc1f3fSmrg 191a2dc1f3fSmrg template<typename _Tp1, typename _Tp2> 192a2dc1f3fSmrg static constexpr const _Tp1&& 193a2dc1f3fSmrg __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept 194a2dc1f3fSmrg { return std::forward<const _Tp1>(__pair.first); } 1951debfc3dSmrg }; 1961debfc3dSmrg 1971debfc3dSmrg template<> 1981debfc3dSmrg struct __pair_get<1> 1991debfc3dSmrg { 2001debfc3dSmrg template<typename _Tp1, typename _Tp2> 2011debfc3dSmrg static constexpr _Tp2& 2021debfc3dSmrg __get(std::pair<_Tp1, _Tp2>& __pair) noexcept 2031debfc3dSmrg { return __pair.second; } 2041debfc3dSmrg 2051debfc3dSmrg template<typename _Tp1, typename _Tp2> 2061debfc3dSmrg static constexpr _Tp2&& 2071debfc3dSmrg __move_get(std::pair<_Tp1, _Tp2>&& __pair) noexcept 2081debfc3dSmrg { return std::forward<_Tp2>(__pair.second); } 2091debfc3dSmrg 2101debfc3dSmrg template<typename _Tp1, typename _Tp2> 2111debfc3dSmrg static constexpr const _Tp2& 2121debfc3dSmrg __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept 2131debfc3dSmrg { return __pair.second; } 214a2dc1f3fSmrg 215a2dc1f3fSmrg template<typename _Tp1, typename _Tp2> 216a2dc1f3fSmrg static constexpr const _Tp2&& 217a2dc1f3fSmrg __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept 218a2dc1f3fSmrg { return std::forward<const _Tp2>(__pair.second); } 2191debfc3dSmrg }; 2201debfc3dSmrg 2211debfc3dSmrg template<std::size_t _Int, class _Tp1, class _Tp2> 2221debfc3dSmrg constexpr typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type& 2231debfc3dSmrg get(std::pair<_Tp1, _Tp2>& __in) noexcept 2241debfc3dSmrg { return __pair_get<_Int>::__get(__in); } 2251debfc3dSmrg 2261debfc3dSmrg template<std::size_t _Int, class _Tp1, class _Tp2> 2271debfc3dSmrg constexpr typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type&& 2281debfc3dSmrg get(std::pair<_Tp1, _Tp2>&& __in) noexcept 2291debfc3dSmrg { return __pair_get<_Int>::__move_get(std::move(__in)); } 2301debfc3dSmrg 2311debfc3dSmrg template<std::size_t _Int, class _Tp1, class _Tp2> 2321debfc3dSmrg constexpr const typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type& 2331debfc3dSmrg get(const std::pair<_Tp1, _Tp2>& __in) noexcept 2341debfc3dSmrg { return __pair_get<_Int>::__const_get(__in); } 2351debfc3dSmrg 236a2dc1f3fSmrg template<std::size_t _Int, class _Tp1, class _Tp2> 237a2dc1f3fSmrg constexpr const typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type&& 238a2dc1f3fSmrg get(const std::pair<_Tp1, _Tp2>&& __in) noexcept 239a2dc1f3fSmrg { return __pair_get<_Int>::__const_move_get(std::move(__in)); } 240a2dc1f3fSmrg 241*8feb0f0bSmrg#if __cplusplus >= 201402L 2421debfc3dSmrg 2431debfc3dSmrg#define __cpp_lib_tuples_by_type 201304 2441debfc3dSmrg 2451debfc3dSmrg template <typename _Tp, typename _Up> 2461debfc3dSmrg constexpr _Tp& 2471debfc3dSmrg get(pair<_Tp, _Up>& __p) noexcept 2481debfc3dSmrg { return __p.first; } 2491debfc3dSmrg 2501debfc3dSmrg template <typename _Tp, typename _Up> 2511debfc3dSmrg constexpr const _Tp& 2521debfc3dSmrg get(const pair<_Tp, _Up>& __p) noexcept 2531debfc3dSmrg { return __p.first; } 2541debfc3dSmrg 2551debfc3dSmrg template <typename _Tp, typename _Up> 2561debfc3dSmrg constexpr _Tp&& 2571debfc3dSmrg get(pair<_Tp, _Up>&& __p) noexcept 2581debfc3dSmrg { return std::move(__p.first); } 2591debfc3dSmrg 2601debfc3dSmrg template <typename _Tp, typename _Up> 261a2dc1f3fSmrg constexpr const _Tp&& 262a2dc1f3fSmrg get(const pair<_Tp, _Up>&& __p) noexcept 263a2dc1f3fSmrg { return std::move(__p.first); } 264a2dc1f3fSmrg 265a2dc1f3fSmrg template <typename _Tp, typename _Up> 2661debfc3dSmrg constexpr _Tp& 2671debfc3dSmrg get(pair<_Up, _Tp>& __p) noexcept 2681debfc3dSmrg { return __p.second; } 2691debfc3dSmrg 2701debfc3dSmrg template <typename _Tp, typename _Up> 2711debfc3dSmrg constexpr const _Tp& 2721debfc3dSmrg get(const pair<_Up, _Tp>& __p) noexcept 2731debfc3dSmrg { return __p.second; } 2741debfc3dSmrg 2751debfc3dSmrg template <typename _Tp, typename _Up> 2761debfc3dSmrg constexpr _Tp&& 2771debfc3dSmrg get(pair<_Up, _Tp>&& __p) noexcept 2781debfc3dSmrg { return std::move(__p.second); } 2791debfc3dSmrg 280a2dc1f3fSmrg template <typename _Tp, typename _Up> 281a2dc1f3fSmrg constexpr const _Tp&& 282a2dc1f3fSmrg get(const pair<_Up, _Tp>&& __p) noexcept 283a2dc1f3fSmrg { return std::move(__p.second); } 284a2dc1f3fSmrg 2851debfc3dSmrg#define __cpp_lib_exchange_function 201304 2861debfc3dSmrg 2871debfc3dSmrg /// Assign @p __new_val to @p __obj and return its previous value. 2881debfc3dSmrg template <typename _Tp, typename _Up = _Tp> 289*8feb0f0bSmrg _GLIBCXX20_CONSTEXPR 2901debfc3dSmrg inline _Tp 2911debfc3dSmrg exchange(_Tp& __obj, _Up&& __new_val) 2921debfc3dSmrg { return std::__exchange(__obj, std::forward<_Up>(__new_val)); } 293*8feb0f0bSmrg 294*8feb0f0bSmrg#endif // C++14 2951debfc3dSmrg 2961debfc3dSmrg // Stores a tuple of indices. Used by tuple and pair, and by bind() to 2971debfc3dSmrg // extract the elements in a tuple. 2981debfc3dSmrg template<size_t... _Indexes> struct _Index_tuple { }; 2991debfc3dSmrg 300a2dc1f3fSmrg#ifdef __has_builtin 301a2dc1f3fSmrg# if __has_builtin(__make_integer_seq) 302a2dc1f3fSmrg# define _GLIBCXX_USE_MAKE_INTEGER_SEQ 1 303a2dc1f3fSmrg# endif 304a2dc1f3fSmrg#endif 3051debfc3dSmrg 3061debfc3dSmrg // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. 3071debfc3dSmrg template<size_t _Num> 3081debfc3dSmrg struct _Build_index_tuple 3091debfc3dSmrg { 310a2dc1f3fSmrg#if _GLIBCXX_USE_MAKE_INTEGER_SEQ 311a2dc1f3fSmrg template<typename, size_t... _Indices> 312a2dc1f3fSmrg using _IdxTuple = _Index_tuple<_Indices...>; 3131debfc3dSmrg 314a2dc1f3fSmrg using __type = __make_integer_seq<_IdxTuple, size_t, _Num>; 315a2dc1f3fSmrg#else 316a2dc1f3fSmrg using __type = _Index_tuple<__integer_pack(_Num)...>; 317a2dc1f3fSmrg#endif 3181debfc3dSmrg }; 3191debfc3dSmrg 3201debfc3dSmrg#if __cplusplus > 201103L 3211debfc3dSmrg 3221debfc3dSmrg#define __cpp_lib_integer_sequence 201304 3231debfc3dSmrg 3241debfc3dSmrg /// Class template integer_sequence 3251debfc3dSmrg template<typename _Tp, _Tp... _Idx> 3261debfc3dSmrg struct integer_sequence 3271debfc3dSmrg { 3281debfc3dSmrg typedef _Tp value_type; 3291debfc3dSmrg static constexpr size_t size() noexcept { return sizeof...(_Idx); } 3301debfc3dSmrg }; 3311debfc3dSmrg 3321debfc3dSmrg /// Alias template make_integer_sequence 3331debfc3dSmrg template<typename _Tp, _Tp _Num> 3341debfc3dSmrg using make_integer_sequence 335a2dc1f3fSmrg#if _GLIBCXX_USE_MAKE_INTEGER_SEQ 336a2dc1f3fSmrg = __make_integer_seq<integer_sequence, _Tp, _Num>; 337a2dc1f3fSmrg#else 338a2dc1f3fSmrg = integer_sequence<_Tp, __integer_pack(_Num)...>; 339a2dc1f3fSmrg#endif 340a2dc1f3fSmrg 341a2dc1f3fSmrg#undef _GLIBCXX_USE_MAKE_INTEGER_SEQ 3421debfc3dSmrg 3431debfc3dSmrg /// Alias template index_sequence 3441debfc3dSmrg template<size_t... _Idx> 3451debfc3dSmrg using index_sequence = integer_sequence<size_t, _Idx...>; 3461debfc3dSmrg 3471debfc3dSmrg /// Alias template make_index_sequence 3481debfc3dSmrg template<size_t _Num> 3491debfc3dSmrg using make_index_sequence = make_integer_sequence<size_t, _Num>; 3501debfc3dSmrg 3511debfc3dSmrg /// Alias template index_sequence_for 3521debfc3dSmrg template<typename... _Types> 3531debfc3dSmrg using index_sequence_for = make_index_sequence<sizeof...(_Types)>; 3541debfc3dSmrg#endif 3551debfc3dSmrg 3561debfc3dSmrg#if __cplusplus > 201402L 3571debfc3dSmrg 3581debfc3dSmrg struct in_place_t { 3591debfc3dSmrg explicit in_place_t() = default; 3601debfc3dSmrg }; 3611debfc3dSmrg 3621debfc3dSmrg inline constexpr in_place_t in_place{}; 3631debfc3dSmrg 3641debfc3dSmrg template<typename _Tp> struct in_place_type_t 3651debfc3dSmrg { 3661debfc3dSmrg explicit in_place_type_t() = default; 3671debfc3dSmrg }; 3681debfc3dSmrg 3691debfc3dSmrg template<typename _Tp> 3701debfc3dSmrg inline constexpr in_place_type_t<_Tp> in_place_type{}; 3711debfc3dSmrg 3721debfc3dSmrg template<size_t _Idx> struct in_place_index_t 3731debfc3dSmrg { 3741debfc3dSmrg explicit in_place_index_t() = default; 3751debfc3dSmrg }; 3761debfc3dSmrg 3771debfc3dSmrg template<size_t _Idx> 3781debfc3dSmrg inline constexpr in_place_index_t<_Idx> in_place_index{}; 3791debfc3dSmrg 3801debfc3dSmrg template<typename> 3811debfc3dSmrg struct __is_in_place_type_impl : false_type 3821debfc3dSmrg { }; 3831debfc3dSmrg 3841debfc3dSmrg template<typename _Tp> 3851debfc3dSmrg struct __is_in_place_type_impl<in_place_type_t<_Tp>> : true_type 3861debfc3dSmrg { }; 3871debfc3dSmrg 3881debfc3dSmrg template<typename _Tp> 3891debfc3dSmrg struct __is_in_place_type 3901debfc3dSmrg : public __is_in_place_type_impl<_Tp> 3911debfc3dSmrg { }; 3921debfc3dSmrg 3931debfc3dSmrg#define __cpp_lib_as_const 201510 3941debfc3dSmrg template<typename _Tp> 3951debfc3dSmrg constexpr add_const_t<_Tp>& as_const(_Tp& __t) noexcept { return __t; } 3961debfc3dSmrg 3971debfc3dSmrg template<typename _Tp> 3981debfc3dSmrg void as_const(const _Tp&&) = delete; 3991debfc3dSmrg 400*8feb0f0bSmrg#if __cplusplus > 201703L 401*8feb0f0bSmrg#define __cpp_lib_integer_comparison_functions 202002L 402*8feb0f0bSmrg 403*8feb0f0bSmrg template<typename _Tp, typename _Up> 404*8feb0f0bSmrg constexpr bool 405*8feb0f0bSmrg cmp_equal(_Tp __t, _Up __u) noexcept 406*8feb0f0bSmrg { 407*8feb0f0bSmrg static_assert(__is_standard_integer<_Tp>::value); 408*8feb0f0bSmrg static_assert(__is_standard_integer<_Up>::value); 409*8feb0f0bSmrg 410*8feb0f0bSmrg if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) 411*8feb0f0bSmrg return __t == __u; 412*8feb0f0bSmrg else if constexpr (is_signed_v<_Tp>) 413*8feb0f0bSmrg return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u; 414*8feb0f0bSmrg else 415*8feb0f0bSmrg return __u >= 0 && __t == make_unsigned_t<_Up>(__u); 416*8feb0f0bSmrg } 417*8feb0f0bSmrg 418*8feb0f0bSmrg template<typename _Tp, typename _Up> 419*8feb0f0bSmrg constexpr bool 420*8feb0f0bSmrg cmp_not_equal(_Tp __t, _Up __u) noexcept 421*8feb0f0bSmrg { return !std::cmp_equal(__t, __u); } 422*8feb0f0bSmrg 423*8feb0f0bSmrg template<typename _Tp, typename _Up> 424*8feb0f0bSmrg constexpr bool 425*8feb0f0bSmrg cmp_less(_Tp __t, _Up __u) noexcept 426*8feb0f0bSmrg { 427*8feb0f0bSmrg static_assert(__is_standard_integer<_Tp>::value); 428*8feb0f0bSmrg static_assert(__is_standard_integer<_Up>::value); 429*8feb0f0bSmrg 430*8feb0f0bSmrg if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) 431*8feb0f0bSmrg return __t < __u; 432*8feb0f0bSmrg else if constexpr (is_signed_v<_Tp>) 433*8feb0f0bSmrg return __t < 0 || make_unsigned_t<_Tp>(__t) < __u; 434*8feb0f0bSmrg else 435*8feb0f0bSmrg return __u >= 0 && __t < make_unsigned_t<_Up>(__u); 436*8feb0f0bSmrg } 437*8feb0f0bSmrg 438*8feb0f0bSmrg template<typename _Tp, typename _Up> 439*8feb0f0bSmrg constexpr bool 440*8feb0f0bSmrg cmp_greater(_Tp __t, _Up __u) noexcept 441*8feb0f0bSmrg { return std::cmp_less(__u, __t); } 442*8feb0f0bSmrg 443*8feb0f0bSmrg template<typename _Tp, typename _Up> 444*8feb0f0bSmrg constexpr bool 445*8feb0f0bSmrg cmp_less_equal(_Tp __t, _Up __u) noexcept 446*8feb0f0bSmrg { return !std::cmp_less(__u, __t); } 447*8feb0f0bSmrg 448*8feb0f0bSmrg template<typename _Tp, typename _Up> 449*8feb0f0bSmrg constexpr bool 450*8feb0f0bSmrg cmp_greater_equal(_Tp __t, _Up __u) noexcept 451*8feb0f0bSmrg { return !std::cmp_less(__t, __u); } 452*8feb0f0bSmrg 453*8feb0f0bSmrg template<typename _Up, typename _Tp> 454*8feb0f0bSmrg constexpr bool 455*8feb0f0bSmrg in_range(_Tp __t) noexcept 456*8feb0f0bSmrg { 457*8feb0f0bSmrg static_assert(__is_standard_integer<_Up>::value); 458*8feb0f0bSmrg static_assert(__is_standard_integer<_Tp>::value); 459*8feb0f0bSmrg using __gnu_cxx::__int_traits; 460*8feb0f0bSmrg 461*8feb0f0bSmrg if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) 462*8feb0f0bSmrg return __int_traits<_Up>::__min <= __t 463*8feb0f0bSmrg && __t <= __int_traits<_Up>::__max; 464*8feb0f0bSmrg else if constexpr (is_signed_v<_Tp>) 465*8feb0f0bSmrg return __t >= 0 466*8feb0f0bSmrg && make_unsigned_t<_Tp>(__t) <= __int_traits<_Up>::__max; 467*8feb0f0bSmrg else 468*8feb0f0bSmrg return __t <= make_unsigned_t<_Up>(__int_traits<_Up>::__max); 469*8feb0f0bSmrg } 470*8feb0f0bSmrg#endif // C++20 4711debfc3dSmrg#endif // C++17 4721debfc3dSmrg 4731debfc3dSmrg_GLIBCXX_END_NAMESPACE_VERSION 4741debfc3dSmrg} // namespace 4751debfc3dSmrg 4761debfc3dSmrg#endif 4771debfc3dSmrg 4781debfc3dSmrg#endif /* _GLIBCXX_UTILITY */ 479