xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/std/utility (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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