(root)/
gcc-13.2.0/
libstdc++-v3/
include/
bits/
functional_hash.h
       1  // functional_hash.h header -*- C++ -*-
       2  
       3  // Copyright (C) 2007-2023 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 bits/functional_hash.h
      26   *  This is an internal header file, included by other library headers.
      27   *  Do not attempt to use it directly. @headername{functional}
      28   */
      29  
      30  #ifndef _FUNCTIONAL_HASH_H
      31  #define _FUNCTIONAL_HASH_H 1
      32  
      33  #pragma GCC system_header
      34  
      35  #include <type_traits>
      36  #include <bits/hash_bytes.h>
      37  
      38  namespace std _GLIBCXX_VISIBILITY(default)
      39  {
      40  _GLIBCXX_BEGIN_NAMESPACE_VERSION
      41  
      42    /** @defgroup hashes Hashes
      43     *  @ingroup functors
      44     *
      45     *   Hashing functors taking a variable type and returning a @c std::size_t.
      46     *
      47     *  @{
      48     */
      49  
      50    template<typename _Result, typename _Arg>
      51      struct __hash_base
      52      {
      53        typedef _Result     result_type _GLIBCXX17_DEPRECATED;
      54        typedef _Arg      argument_type _GLIBCXX17_DEPRECATED;
      55      };
      56  
      57    /// Primary class template hash.
      58    template<typename _Tp>
      59      struct hash;
      60  
      61    template<typename _Tp, typename = void>
      62      struct __poison_hash
      63      {
      64        static constexpr bool __enable_hash_call = false;
      65      private:
      66        // Private rather than deleted to be non-trivially-copyable.
      67        __poison_hash(__poison_hash&&);
      68        ~__poison_hash();
      69      };
      70  
      71    template<typename _Tp>
      72      struct __poison_hash<_Tp, __void_t<decltype(hash<_Tp>()(declval<_Tp>()))>>
      73      {
      74        static constexpr bool __enable_hash_call = true;
      75      };
      76  
      77    // Helper struct for SFINAE-poisoning non-enum types.
      78    template<typename _Tp, bool = is_enum<_Tp>::value>
      79      struct __hash_enum
      80      {
      81      private:
      82        // Private rather than deleted to be non-trivially-copyable.
      83        __hash_enum(__hash_enum&&);
      84        ~__hash_enum();
      85      };
      86  
      87    // Helper struct for hash with enum types.
      88    template<typename _Tp>
      89      struct __hash_enum<_Tp, true> : public __hash_base<size_t, _Tp>
      90      {
      91        size_t
      92        operator()(_Tp __val) const noexcept
      93        {
      94         using __type = typename underlying_type<_Tp>::type;
      95         return hash<__type>{}(static_cast<__type>(__val));
      96        }
      97      };
      98  
      99    /// Primary class template hash, usable for enum types only.
     100    // Use with non-enum types still SFINAES.
     101    template<typename _Tp>
     102      struct hash : __hash_enum<_Tp>
     103      { };
     104  
     105    /// Partial specializations for pointer types.
     106    template<typename _Tp>
     107      struct hash<_Tp*> : public __hash_base<size_t, _Tp*>
     108      {
     109        size_t
     110        operator()(_Tp* __p) const noexcept
     111        { return reinterpret_cast<size_t>(__p); }
     112      };
     113  
     114    // Explicit specializations for integer types.
     115  #define _Cxx_hashtable_define_trivial_hash(_Tp) 	\
     116    template<>						\
     117      struct hash<_Tp> : public __hash_base<size_t, _Tp>  \
     118      {                                                   \
     119        size_t                                            \
     120        operator()(_Tp __val) const noexcept              \
     121        { return static_cast<size_t>(__val); }            \
     122      };
     123  
     124    /// Explicit specialization for bool.
     125    _Cxx_hashtable_define_trivial_hash(bool)
     126  
     127    /// Explicit specialization for char.
     128    _Cxx_hashtable_define_trivial_hash(char)
     129  
     130    /// Explicit specialization for signed char.
     131    _Cxx_hashtable_define_trivial_hash(signed char)
     132  
     133    /// Explicit specialization for unsigned char.
     134    _Cxx_hashtable_define_trivial_hash(unsigned char)
     135  
     136    /// Explicit specialization for wchar_t.
     137    _Cxx_hashtable_define_trivial_hash(wchar_t)
     138  
     139  #ifdef _GLIBCXX_USE_CHAR8_T
     140    /// Explicit specialization for char8_t.
     141    _Cxx_hashtable_define_trivial_hash(char8_t)
     142  #endif
     143  
     144    /// Explicit specialization for char16_t.
     145    _Cxx_hashtable_define_trivial_hash(char16_t)
     146  
     147    /// Explicit specialization for char32_t.
     148    _Cxx_hashtable_define_trivial_hash(char32_t)
     149  
     150    /// Explicit specialization for short.
     151    _Cxx_hashtable_define_trivial_hash(short)
     152  
     153    /// Explicit specialization for int.
     154    _Cxx_hashtable_define_trivial_hash(int)
     155  
     156    /// Explicit specialization for long.
     157    _Cxx_hashtable_define_trivial_hash(long)
     158  
     159    /// Explicit specialization for long long.
     160    _Cxx_hashtable_define_trivial_hash(long long)
     161  
     162    /// Explicit specialization for unsigned short.
     163    _Cxx_hashtable_define_trivial_hash(unsigned short)
     164  
     165    /// Explicit specialization for unsigned int.
     166    _Cxx_hashtable_define_trivial_hash(unsigned int)
     167  
     168    /// Explicit specialization for unsigned long.
     169    _Cxx_hashtable_define_trivial_hash(unsigned long)
     170  
     171    /// Explicit specialization for unsigned long long.
     172    _Cxx_hashtable_define_trivial_hash(unsigned long long)
     173  
     174  #ifdef __GLIBCXX_TYPE_INT_N_0
     175    __extension__
     176    _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_0)
     177    __extension__
     178    _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_0 unsigned)
     179  #endif
     180  #ifdef __GLIBCXX_TYPE_INT_N_1
     181    __extension__
     182    _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_1)
     183    __extension__
     184    _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_1 unsigned)
     185  #endif
     186  #ifdef __GLIBCXX_TYPE_INT_N_2
     187    __extension__
     188    _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_2)
     189    __extension__
     190    _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_2 unsigned)
     191  #endif
     192  #ifdef __GLIBCXX_TYPE_INT_N_3
     193    __extension__
     194    _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3)
     195    __extension__
     196    _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3 unsigned)
     197  #endif
     198  
     199  #undef _Cxx_hashtable_define_trivial_hash
     200  
     201    struct _Hash_impl
     202    {
     203      static size_t
     204      hash(const void* __ptr, size_t __clength,
     205  	 size_t __seed = static_cast<size_t>(0xc70f6907UL))
     206      { return _Hash_bytes(__ptr, __clength, __seed); }
     207  
     208      template<typename _Tp>
     209        static size_t
     210        hash(const _Tp& __val)
     211        { return hash(&__val, sizeof(__val)); }
     212  
     213      template<typename _Tp>
     214        static size_t
     215        __hash_combine(const _Tp& __val, size_t __hash)
     216        { return hash(&__val, sizeof(__val), __hash); }
     217    };
     218  
     219    // A hash function similar to FNV-1a (see PR59406 for how it differs).
     220    struct _Fnv_hash_impl
     221    {
     222      static size_t
     223      hash(const void* __ptr, size_t __clength,
     224  	 size_t __seed = static_cast<size_t>(2166136261UL))
     225      { return _Fnv_hash_bytes(__ptr, __clength, __seed); }
     226  
     227      template<typename _Tp>
     228        static size_t
     229        hash(const _Tp& __val)
     230        { return hash(&__val, sizeof(__val)); }
     231  
     232      template<typename _Tp>
     233        static size_t
     234        __hash_combine(const _Tp& __val, size_t __hash)
     235        { return hash(&__val, sizeof(__val), __hash); }
     236    };
     237  
     238    /// Specialization for float.
     239    template<>
     240      struct hash<float> : public __hash_base<size_t, float>
     241      {
     242        size_t
     243        operator()(float __val) const noexcept
     244        {
     245  	// 0 and -0 both hash to zero.
     246  	return __val != 0.0f ? std::_Hash_impl::hash(__val) : 0;
     247        }
     248      };
     249  
     250    /// Specialization for double.
     251    template<>
     252      struct hash<double> : public __hash_base<size_t, double>
     253      {
     254        size_t
     255        operator()(double __val) const noexcept
     256        {
     257  	// 0 and -0 both hash to zero.
     258  	return __val != 0.0 ? std::_Hash_impl::hash(__val) : 0;
     259        }
     260      };
     261  
     262    /// Specialization for long double.
     263    template<>
     264      struct hash<long double>
     265      : public __hash_base<size_t, long double>
     266      {
     267        _GLIBCXX_PURE size_t
     268        operator()(long double __val) const noexcept;
     269      };
     270  
     271  #if __cplusplus >= 201703L
     272    template<>
     273      struct hash<nullptr_t> : public __hash_base<size_t, nullptr_t>
     274      {
     275        size_t
     276        operator()(nullptr_t) const noexcept
     277        { return 0; }
     278      };
     279  #endif
     280  
     281    /// @} group hashes
     282  
     283    /** Hint about performance of hash functions.
     284     *
     285     * If a given hash function object is not fast, the hash-based containers
     286     * will cache the hash code.
     287     * The default behavior is to consider that hashers are fast unless specified
     288     * otherwise.
     289     *
     290     * Users can specialize this for their own hash functions in order to force
     291     * caching of hash codes in unordered containers. Specializing this trait
     292     * affects the ABI of the unordered containers, so use it carefully.
     293     */
     294    template<typename _Hash>
     295      struct __is_fast_hash : public std::true_type
     296      { };
     297  
     298    template<>
     299      struct __is_fast_hash<hash<long double>> : public std::false_type
     300      { };
     301  
     302  _GLIBCXX_END_NAMESPACE_VERSION
     303  } // namespace
     304  
     305  #endif // _FUNCTIONAL_HASH_H