1// Utilities used throughout the library -*- C++ -*- 2 3// Copyright (C) 2004-2022 Free Software Foundation, Inc. 4// 5// This file is part of the GNU ISO C++ Library. This library is free 6// software; you can redistribute it and/or modify it under the 7// terms of the GNU General Public License as published by the 8// Free Software Foundation; either version 3, or (at your option) 9// any later version. 10 11// This library is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14// GNU General Public License for more details. 15 16// Under Section 7 of GPL version 3, you are granted additional 17// permissions described in the GCC Runtime Library Exception, version 18// 3.1, as published by the Free Software Foundation. 19 20// You should have received a copy of the GNU General Public License and 21// a copy of the GCC Runtime Library Exception along with this program; 22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23// <http://www.gnu.org/licenses/>. 24 25/** @file include/bits/utility.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{utility} 28 * 29 * This file contains the parts of `<utility>` needed by other headers, 30 * so they don't need to include the whole of `<utility>`. 31 */ 32 33#ifndef _GLIBCXX_UTILITY_H 34#define _GLIBCXX_UTILITY_H 1 35 36#pragma GCC system_header 37 38#if __cplusplus >= 201103L 39 40#include <type_traits> 41#include <bits/move.h> 42 43namespace std _GLIBCXX_VISIBILITY(default) 44{ 45_GLIBCXX_BEGIN_NAMESPACE_VERSION 46 47 /// Finds the size of a given tuple type. 48 template<typename _Tp> 49 struct tuple_size; 50 51 // _GLIBCXX_RESOLVE_LIB_DEFECTS 52 // 2313. tuple_size should always derive from integral_constant<size_t, N> 53 // 2770. tuple_size<const T> specialization is not SFINAE compatible 54 55 template<typename _Tp, 56 typename _Up = typename remove_cv<_Tp>::type, 57 typename = typename enable_if<is_same<_Tp, _Up>::value>::type, 58 size_t = tuple_size<_Tp>::value> 59 using __enable_if_has_tuple_size = _Tp; 60 61 template<typename _Tp> 62 struct tuple_size<const __enable_if_has_tuple_size<_Tp>> 63 : public tuple_size<_Tp> { }; 64 65 template<typename _Tp> 66 struct tuple_size<volatile __enable_if_has_tuple_size<_Tp>> 67 : public tuple_size<_Tp> { }; 68 69 template<typename _Tp> 70 struct tuple_size<const volatile __enable_if_has_tuple_size<_Tp>> 71 : public tuple_size<_Tp> { }; 72 73#if __cplusplus >= 201703L 74 template<typename _Tp> 75 inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value; 76#endif 77 78 /// Gives the type of the ith element of a given tuple type. 79 template<size_t __i, typename _Tp> 80 struct tuple_element; 81 82 // Duplicate of C++14's tuple_element_t for internal use in C++11 mode 83 template<size_t __i, typename _Tp> 84 using __tuple_element_t = typename tuple_element<__i, _Tp>::type; 85 86 template<size_t __i, typename _Tp> 87 struct tuple_element<__i, const _Tp> 88 { 89 typedef typename add_const<__tuple_element_t<__i, _Tp>>::type type; 90 }; 91 92 template<size_t __i, typename _Tp> 93 struct tuple_element<__i, volatile _Tp> 94 { 95 typedef typename add_volatile<__tuple_element_t<__i, _Tp>>::type type; 96 }; 97 98 template<size_t __i, typename _Tp> 99 struct tuple_element<__i, const volatile _Tp> 100 { 101 typedef typename add_cv<__tuple_element_t<__i, _Tp>>::type type; 102 }; 103 104#if __cplusplus >= 201402L 105 106 // Return the index of _Tp in _Types, if it occurs exactly once. 107 // Otherwise, return sizeof...(_Types). 108 template<typename _Tp, typename... _Types> 109 constexpr size_t 110 __find_uniq_type_in_pack() 111 { 112 constexpr size_t __sz = sizeof...(_Types); 113 constexpr bool __found[__sz] = { __is_same(_Tp, _Types) ... }; 114 size_t __n = __sz; 115 for (size_t __i = 0; __i < __sz; ++__i) 116 { 117 if (__found[__i]) 118 { 119 if (__n < __sz) // more than one _Tp found 120 return __sz; 121 __n = __i; 122 } 123 } 124 return __n; 125 } 126 127// The standard says this macro and alias template should be in <tuple> but we 128// define them here, to be available in <array>, <utility> and <ranges> too. 129// _GLIBCXX_RESOLVE_LIB_DEFECTS 130// 3378. tuple_size_v/tuple_element_t should be available when 131// tuple_size/tuple_element are 132#define __cpp_lib_tuple_element_t 201402L 133 134 template<size_t __i, typename _Tp> 135 using tuple_element_t = typename tuple_element<__i, _Tp>::type; 136#endif // C++14 137 138 // Stores a tuple of indices. Used by tuple and pair, and by bind() to 139 // extract the elements in a tuple. 140 template<size_t... _Indexes> struct _Index_tuple { }; 141 142 // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. 143 template<size_t _Num> 144 struct _Build_index_tuple 145 { 146#if __has_builtin(__make_integer_seq) 147 template<typename, size_t... _Indices> 148 using _IdxTuple = _Index_tuple<_Indices...>; 149 150 // Clang defines __make_integer_seq for this purpose. 151 using __type = __make_integer_seq<_IdxTuple, size_t, _Num>; 152#else 153 // For GCC and other compilers, use __integer_pack instead. 154 using __type = _Index_tuple<__integer_pack(_Num)...>; 155#endif 156 }; 157 158#if __cplusplus >= 201402L 159 160#define __cpp_lib_integer_sequence 201304L 161 162 /// Class template integer_sequence 163 template<typename _Tp, _Tp... _Idx> 164 struct integer_sequence 165 { 166 typedef _Tp value_type; 167 static constexpr size_t size() noexcept { return sizeof...(_Idx); } 168 }; 169 170 /// Alias template make_integer_sequence 171 template<typename _Tp, _Tp _Num> 172 using make_integer_sequence 173#if __has_builtin(__make_integer_seq) 174 = __make_integer_seq<integer_sequence, _Tp, _Num>; 175#else 176 = integer_sequence<_Tp, __integer_pack(_Num)...>; 177#endif 178 179 /// Alias template index_sequence 180 template<size_t... _Idx> 181 using index_sequence = integer_sequence<size_t, _Idx...>; 182 183 /// Alias template make_index_sequence 184 template<size_t _Num> 185 using make_index_sequence = make_integer_sequence<size_t, _Num>; 186 187 /// Alias template index_sequence_for 188 template<typename... _Types> 189 using index_sequence_for = make_index_sequence<sizeof...(_Types)>; 190 191#if __cplusplus >= 201703L 192 193 struct in_place_t { 194 explicit in_place_t() = default; 195 }; 196 197 inline constexpr in_place_t in_place{}; 198 199 template<typename _Tp> struct in_place_type_t 200 { 201 explicit in_place_type_t() = default; 202 }; 203 204 template<typename _Tp> 205 inline constexpr in_place_type_t<_Tp> in_place_type{}; 206 207 template<size_t _Idx> struct in_place_index_t 208 { 209 explicit in_place_index_t() = default; 210 }; 211 212 template<size_t _Idx> 213 inline constexpr in_place_index_t<_Idx> in_place_index{}; 214 215 template<typename> 216 inline constexpr bool __is_in_place_type_v = false; 217 218 template<typename _Tp> 219 inline constexpr bool __is_in_place_type_v<in_place_type_t<_Tp>> = true; 220 221 template<typename _Tp> 222 using __is_in_place_type = bool_constant<__is_in_place_type_v<_Tp>>; 223 224#endif // C++17 225#endif // C++14 226 227 template<size_t _Np, typename... _Types> 228 struct _Nth_type 229 { }; 230 231 template<typename _Tp0, typename... _Rest> 232 struct _Nth_type<0, _Tp0, _Rest...> 233 { using type = _Tp0; }; 234 235 template<typename _Tp0, typename _Tp1, typename... _Rest> 236 struct _Nth_type<1, _Tp0, _Tp1, _Rest...> 237 { using type = _Tp1; }; 238 239 template<typename _Tp0, typename _Tp1, typename _Tp2, typename... _Rest> 240 struct _Nth_type<2, _Tp0, _Tp1, _Tp2, _Rest...> 241 { using type = _Tp2; }; 242 243 template<size_t _Np, typename _Tp0, typename _Tp1, typename _Tp2, 244 typename... _Rest> 245#if __cpp_concepts 246 requires (_Np >= 3) 247#endif 248 struct _Nth_type<_Np, _Tp0, _Tp1, _Tp2, _Rest...> 249 : _Nth_type<_Np - 3, _Rest...> 250 { }; 251 252#if ! __cpp_concepts // Need additional specializations to avoid ambiguities. 253 template<typename _Tp0, typename _Tp1, typename... _Rest> 254 struct _Nth_type<0, _Tp0, _Tp1, _Rest...> 255 { using type = _Tp0; }; 256 257 template<typename _Tp0, typename _Tp1, typename _Tp2, typename... _Rest> 258 struct _Nth_type<0, _Tp0, _Tp1, _Tp2, _Rest...> 259 { using type = _Tp0; }; 260 261 template<typename _Tp0, typename _Tp1, typename _Tp2, typename... _Rest> 262 struct _Nth_type<1, _Tp0, _Tp1, _Tp2, _Rest...> 263 { using type = _Tp1; }; 264#endif 265 266_GLIBCXX_END_NAMESPACE_VERSION 267} // namespace 268 269#endif // C++11 270#endif /* _GLIBCXX_UTILITY_H */ 271