// Utilities used throughout the library -*- C++ -*-
// Copyright (C) 2004-2024 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// .
/** @file include/bits/utility.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{utility}
*
* This file contains the parts of `` needed by other headers,
* so they don't need to include the whole of ``.
*/
#ifndef _GLIBCXX_UTILITY_H
#define _GLIBCXX_UTILITY_H 1
#pragma GCC system_header
#if __cplusplus >= 201103L
#include
#include
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Finds the size of a given tuple type.
template
struct tuple_size;
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2313. tuple_size should always derive from integral_constant
// 2770. tuple_size specialization is not SFINAE compatible
template::type,
typename = typename enable_if::value>::type,
size_t = tuple_size<_Tp>::value>
using __enable_if_has_tuple_size = _Tp;
template
struct tuple_size>
: public tuple_size<_Tp> { };
template
struct tuple_size>
: public tuple_size<_Tp> { };
template
struct tuple_size>
: public tuple_size<_Tp> { };
#if __cplusplus >= 201703L
template
inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value;
#endif
/// Gives the type of the ith element of a given tuple type.
template
struct tuple_element;
// Duplicate of C++14's tuple_element_t for internal use in C++11 mode
template
using __tuple_element_t = typename tuple_element<__i, _Tp>::type;
template
struct tuple_element<__i, const _Tp>
{
using type = const __tuple_element_t<__i, _Tp>;
};
template
struct tuple_element<__i, volatile _Tp>
{
using type = volatile __tuple_element_t<__i, _Tp>;
};
template
struct tuple_element<__i, const volatile _Tp>
{
using type = const volatile __tuple_element_t<__i, _Tp>;
};
#if __cplusplus >= 201402L
// Return the index of _Tp in _Types, if it occurs exactly once.
// Otherwise, return sizeof...(_Types).
template
constexpr size_t
__find_uniq_type_in_pack()
{
constexpr size_t __sz = sizeof...(_Types);
constexpr bool __found[__sz] = { __is_same(_Tp, _Types) ... };
size_t __n = __sz;
for (size_t __i = 0; __i < __sz; ++__i)
{
if (__found[__i])
{
if (__n < __sz) // more than one _Tp found
return __sz;
__n = __i;
}
}
return __n;
}
#endif // C++14
// The standard says this macro and alias template should be in but we
// define them here, to be available in , and too.
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 3378. tuple_size_v/tuple_element_t should be available when
// tuple_size/tuple_element are
#ifdef __glibcxx_tuple_element_t // C++ >= 14
template
using tuple_element_t = typename tuple_element<__i, _Tp>::type;
#endif
// Stores a tuple of indices. Used by tuple and pair, and by bind() to
// extract the elements in a tuple.
template struct _Index_tuple { };
// Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
template
struct _Build_index_tuple
{
#if __has_builtin(__make_integer_seq)
template
using _IdxTuple = _Index_tuple<_Indices...>;
// Clang defines __make_integer_seq for this purpose.
using __type = __make_integer_seq<_IdxTuple, size_t, _Num>;
#else
// For GCC and other compilers, use __integer_pack instead.
using __type = _Index_tuple<__integer_pack(_Num)...>;
#endif
};
#ifdef __glibcxx_integer_sequence // C++ >= 14
/// Class template integer_sequence
template
struct integer_sequence
{
#if __cplusplus >= 202002L
static_assert(is_integral_v<_Tp>);
#endif
typedef _Tp value_type;
static constexpr size_t size() noexcept { return sizeof...(_Idx); }
};
/// Alias template make_integer_sequence
template
using make_integer_sequence
#if __has_builtin(__make_integer_seq)
= __make_integer_seq;
#else
= integer_sequence<_Tp, __integer_pack(_Num)...>;
#endif
/// Alias template index_sequence
template
using index_sequence = integer_sequence;
/// Alias template make_index_sequence
template
using make_index_sequence = make_integer_sequence;
/// Alias template index_sequence_for
template
using index_sequence_for = make_index_sequence;
#endif // __glibcxx_integer_sequence
#if __cplusplus >= 201703L
struct in_place_t {
explicit in_place_t() = default;
};
inline constexpr in_place_t in_place{};
template struct in_place_type_t
{
explicit in_place_type_t() = default;
};
template
inline constexpr in_place_type_t<_Tp> in_place_type{};
template struct in_place_index_t
{
explicit in_place_index_t() = default;
};
template
inline constexpr in_place_index_t<_Idx> in_place_index{};
template
inline constexpr bool __is_in_place_type_v = false;
template
inline constexpr bool __is_in_place_type_v> = true;
template
using __is_in_place_type = bool_constant<__is_in_place_type_v<_Tp>>;
template
inline constexpr bool __is_in_place_index_v = false;
template
inline constexpr bool __is_in_place_index_v> = true;
#endif // C++17
#if _GLIBCXX_USE_BUILTIN_TRAIT(__type_pack_element)
template
struct _Nth_type
{ using type = __type_pack_element<_Np, _Types...>; };
#else
template
struct _Nth_type
{ };
template
struct _Nth_type<0, _Tp0, _Rest...>
{ using type = _Tp0; };
template
struct _Nth_type<1, _Tp0, _Tp1, _Rest...>
{ using type = _Tp1; };
template
struct _Nth_type<2, _Tp0, _Tp1, _Tp2, _Rest...>
{ using type = _Tp2; };
template
#if __cpp_concepts
requires (_Np >= 3)
#endif
struct _Nth_type<_Np, _Tp0, _Tp1, _Tp2, _Rest...>
: _Nth_type<_Np - 3, _Rest...>
{ };
#if ! __cpp_concepts // Need additional specializations to avoid ambiguities.
template
struct _Nth_type<0, _Tp0, _Tp1, _Tp2, _Rest...>
{ using type = _Tp0; };
template
struct _Nth_type<1, _Tp0, _Tp1, _Tp2, _Rest...>
{ using type = _Tp1; };
#endif
#endif
#if __glibcxx_ranges
namespace ranges::__detail
{
template
inline constexpr bool __is_subrange = false;
} // namespace __detail
#endif
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
#endif // C++11
#endif /* _GLIBCXX_UTILITY_H */