hash.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. // Copyright 2005-2014 Daniel James.
  2. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  3. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  4. // Based on Peter Dimov's proposal
  5. // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
  6. // issue 6.18.
  7. //
  8. // This also contains public domain code from MurmurHash. From the
  9. // MurmurHash header:
  10. // MurmurHash3 was written by Austin Appleby, and is placed in the public
  11. // domain. The author hereby disclaims copyright to this source code.
  12. #if !defined(BOOST_FUNCTIONAL_HASH_HASH_HPP)
  13. #define BOOST_FUNCTIONAL_HASH_HASH_HPP
  14. #include <boost/container_hash/hash_fwd.hpp>
  15. #include <functional>
  16. #include <boost/container_hash/detail/hash_float.hpp>
  17. #include <string>
  18. #include <boost/limits.hpp>
  19. #include <boost/type_traits/is_enum.hpp>
  20. #include <boost/type_traits/is_integral.hpp>
  21. #include <boost/core/enable_if.hpp>
  22. #include <boost/cstdint.hpp>
  23. #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
  24. #include <boost/type_traits/is_pointer.hpp>
  25. #endif
  26. #if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
  27. #include <typeindex>
  28. #endif
  29. #if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
  30. #include <system_error>
  31. #endif
  32. #if defined(BOOST_MSVC)
  33. #pragma warning(push)
  34. #if BOOST_MSVC >= 1400
  35. #pragma warning(disable:6295) // Ill-defined for-loop : 'unsigned int' values
  36. // are always of range '0' to '4294967295'.
  37. // Loop executes infinitely.
  38. #endif
  39. #endif
  40. #if BOOST_WORKAROUND(__GNUC__, < 3) \
  41. && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
  42. #define BOOST_HASH_CHAR_TRAITS string_char_traits
  43. #else
  44. #define BOOST_HASH_CHAR_TRAITS char_traits
  45. #endif
  46. #if defined(_MSC_VER)
  47. # define BOOST_FUNCTIONAL_HASH_ROTL32(x, r) _rotl(x,r)
  48. #else
  49. # define BOOST_FUNCTIONAL_HASH_ROTL32(x, r) (x << r) | (x >> (32 - r))
  50. #endif
  51. // Detect whether standard library has C++17 headers
  52. #if !defined(BOOST_HASH_CXX17)
  53. # if defined(BOOST_MSVC)
  54. # if defined(_HAS_CXX17) && _HAS_CXX17
  55. # define BOOST_HASH_CXX17 1
  56. # endif
  57. # elif defined(__cplusplus) && __cplusplus >= 201703
  58. # define BOOST_HASH_CXX17 1
  59. # endif
  60. #endif
  61. #if !defined(BOOST_HASH_CXX17)
  62. # define BOOST_HASH_CXX17 0
  63. #endif
  64. #if BOOST_HASH_CXX17 && defined(__has_include)
  65. # if !defined(BOOST_HASH_HAS_STRING_VIEW) && __has_include(<string_view>)
  66. # define BOOST_HASH_HAS_STRING_VIEW 1
  67. # endif
  68. # if !defined(BOOST_HASH_HAS_OPTIONAL) && __has_include(<optional>)
  69. # define BOOST_HASH_HAS_OPTIONAL 1
  70. # endif
  71. # if !defined(BOOST_HASH_HAS_VARIANT) && __has_include(<variant>)
  72. # define BOOST_HASH_HAS_VARIANT 1
  73. # endif
  74. #endif
  75. #if !defined(BOOST_HASH_HAS_STRING_VIEW)
  76. # define BOOST_HASH_HAS_STRING_VIEW 0
  77. #endif
  78. #if !defined(BOOST_HASH_HAS_OPTIONAL)
  79. # define BOOST_HASH_HAS_OPTIONAL 0
  80. #endif
  81. #if !defined(BOOST_HASH_HAS_VARIANT)
  82. # define BOOST_HASH_HAS_VARIANT 0
  83. #endif
  84. #if BOOST_HASH_HAS_STRING_VIEW
  85. # include <string_view>
  86. #endif
  87. #if BOOST_HASH_HAS_OPTIONAL
  88. # include <optional>
  89. #endif
  90. #if BOOST_HASH_HAS_VARIANT
  91. # include <variant>
  92. #endif
  93. namespace boost
  94. {
  95. namespace hash_detail
  96. {
  97. #if defined(_HAS_AUTO_PTR_ETC) && !_HAS_AUTO_PTR_ETC
  98. template <typename T>
  99. struct hash_base
  100. {
  101. typedef T argument_type;
  102. typedef std::size_t result_type;
  103. };
  104. #else
  105. template <typename T>
  106. struct hash_base : std::unary_function<T, std::size_t> {};
  107. #endif
  108. struct enable_hash_value { typedef std::size_t type; };
  109. template <typename T> struct basic_numbers {};
  110. template <typename T> struct long_numbers;
  111. template <typename T> struct ulong_numbers;
  112. template <typename T> struct float_numbers {};
  113. template <> struct basic_numbers<bool> :
  114. boost::hash_detail::enable_hash_value {};
  115. template <> struct basic_numbers<char> :
  116. boost::hash_detail::enable_hash_value {};
  117. template <> struct basic_numbers<unsigned char> :
  118. boost::hash_detail::enable_hash_value {};
  119. template <> struct basic_numbers<signed char> :
  120. boost::hash_detail::enable_hash_value {};
  121. template <> struct basic_numbers<short> :
  122. boost::hash_detail::enable_hash_value {};
  123. template <> struct basic_numbers<unsigned short> :
  124. boost::hash_detail::enable_hash_value {};
  125. template <> struct basic_numbers<int> :
  126. boost::hash_detail::enable_hash_value {};
  127. template <> struct basic_numbers<unsigned int> :
  128. boost::hash_detail::enable_hash_value {};
  129. template <> struct basic_numbers<long> :
  130. boost::hash_detail::enable_hash_value {};
  131. template <> struct basic_numbers<unsigned long> :
  132. boost::hash_detail::enable_hash_value {};
  133. #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  134. template <> struct basic_numbers<wchar_t> :
  135. boost::hash_detail::enable_hash_value {};
  136. #endif
  137. #if !defined(BOOST_NO_CXX11_CHAR16_T)
  138. template <> struct basic_numbers<char16_t> :
  139. boost::hash_detail::enable_hash_value {};
  140. #endif
  141. #if !defined(BOOST_NO_CXX11_CHAR32_T)
  142. template <> struct basic_numbers<char32_t> :
  143. boost::hash_detail::enable_hash_value {};
  144. #endif
  145. // long_numbers is defined like this to allow for separate
  146. // specialization for long_long and int128_type, in case
  147. // they conflict.
  148. template <typename T> struct long_numbers2 {};
  149. template <typename T> struct ulong_numbers2 {};
  150. template <typename T> struct long_numbers : long_numbers2<T> {};
  151. template <typename T> struct ulong_numbers : ulong_numbers2<T> {};
  152. #if !defined(BOOST_NO_LONG_LONG)
  153. template <> struct long_numbers<boost::long_long_type> :
  154. boost::hash_detail::enable_hash_value {};
  155. template <> struct ulong_numbers<boost::ulong_long_type> :
  156. boost::hash_detail::enable_hash_value {};
  157. #endif
  158. #if defined(BOOST_HAS_INT128)
  159. template <> struct long_numbers2<boost::int128_type> :
  160. boost::hash_detail::enable_hash_value {};
  161. template <> struct ulong_numbers2<boost::uint128_type> :
  162. boost::hash_detail::enable_hash_value {};
  163. #endif
  164. template <> struct float_numbers<float> :
  165. boost::hash_detail::enable_hash_value {};
  166. template <> struct float_numbers<double> :
  167. boost::hash_detail::enable_hash_value {};
  168. template <> struct float_numbers<long double> :
  169. boost::hash_detail::enable_hash_value {};
  170. }
  171. template <typename T>
  172. typename boost::hash_detail::basic_numbers<T>::type hash_value(T);
  173. template <typename T>
  174. typename boost::hash_detail::long_numbers<T>::type hash_value(T);
  175. template <typename T>
  176. typename boost::hash_detail::ulong_numbers<T>::type hash_value(T);
  177. template <typename T>
  178. typename boost::enable_if<boost::is_enum<T>, std::size_t>::type
  179. hash_value(T);
  180. #if !BOOST_WORKAROUND(__DMC__, <= 0x848)
  181. template <class T> std::size_t hash_value(T* const&);
  182. #else
  183. template <class T> std::size_t hash_value(T*);
  184. #endif
  185. #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  186. template< class T, unsigned N >
  187. std::size_t hash_value(const T (&x)[N]);
  188. template< class T, unsigned N >
  189. std::size_t hash_value(T (&x)[N]);
  190. #endif
  191. template <class Ch, class A>
  192. std::size_t hash_value(
  193. std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const&);
  194. #if BOOST_HASH_HAS_STRING_VIEW
  195. template <class Ch>
  196. std::size_t hash_value(
  197. std::basic_string_view<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch> > const&);
  198. #endif
  199. template <typename T>
  200. typename boost::hash_detail::float_numbers<T>::type hash_value(T);
  201. #if BOOST_HASH_HAS_OPTIONAL
  202. template <typename T>
  203. std::size_t hash_value(std::optional<T> const&);
  204. #endif
  205. #if BOOST_HASH_HAS_VARIANT
  206. std::size_t hash_value(std::monostate);
  207. template <typename... Types>
  208. std::size_t hash_value(std::variant<Types...> const&);
  209. #endif
  210. #if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
  211. std::size_t hash_value(std::type_index);
  212. #endif
  213. #if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
  214. std::size_t hash_value(std::error_code const&);
  215. std::size_t hash_value(std::error_condition const&);
  216. #endif
  217. // Implementation
  218. namespace hash_detail
  219. {
  220. template <class T>
  221. inline std::size_t hash_value_signed(T val)
  222. {
  223. const unsigned int size_t_bits = std::numeric_limits<std::size_t>::digits;
  224. // ceiling(std::numeric_limits<T>::digits / size_t_bits) - 1
  225. const int length = (std::numeric_limits<T>::digits - 1)
  226. / static_cast<int>(size_t_bits);
  227. std::size_t seed = 0;
  228. T positive = val < 0 ? -1 - val : val;
  229. // Hopefully, this loop can be unrolled.
  230. for(unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits)
  231. {
  232. seed ^= (std::size_t) (positive >> i) + (seed<<6) + (seed>>2);
  233. }
  234. seed ^= (std::size_t) val + (seed<<6) + (seed>>2);
  235. return seed;
  236. }
  237. template <class T>
  238. inline std::size_t hash_value_unsigned(T val)
  239. {
  240. const unsigned int size_t_bits = std::numeric_limits<std::size_t>::digits;
  241. // ceiling(std::numeric_limits<T>::digits / size_t_bits) - 1
  242. const int length = (std::numeric_limits<T>::digits - 1)
  243. / static_cast<int>(size_t_bits);
  244. std::size_t seed = 0;
  245. // Hopefully, this loop can be unrolled.
  246. for(unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits)
  247. {
  248. seed ^= (std::size_t) (val >> i) + (seed<<6) + (seed>>2);
  249. }
  250. seed ^= (std::size_t) val + (seed<<6) + (seed>>2);
  251. return seed;
  252. }
  253. template <typename SizeT>
  254. inline void hash_combine_impl(SizeT& seed, SizeT value)
  255. {
  256. seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
  257. }
  258. inline void hash_combine_impl(boost::uint32_t& h1,
  259. boost::uint32_t k1)
  260. {
  261. const uint32_t c1 = 0xcc9e2d51;
  262. const uint32_t c2 = 0x1b873593;
  263. k1 *= c1;
  264. k1 = BOOST_FUNCTIONAL_HASH_ROTL32(k1,15);
  265. k1 *= c2;
  266. h1 ^= k1;
  267. h1 = BOOST_FUNCTIONAL_HASH_ROTL32(h1,13);
  268. h1 = h1*5+0xe6546b64;
  269. }
  270. // Don't define 64-bit hash combine on platforms without 64 bit integers,
  271. // and also not for 32-bit gcc as it warns about the 64-bit constant.
  272. #if !defined(BOOST_NO_INT64_T) && \
  273. !(defined(__GNUC__) && ULONG_MAX == 0xffffffff)
  274. inline void hash_combine_impl(boost::uint64_t& h,
  275. boost::uint64_t k)
  276. {
  277. const boost::uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
  278. const int r = 47;
  279. k *= m;
  280. k ^= k >> r;
  281. k *= m;
  282. h ^= k;
  283. h *= m;
  284. // Completely arbitrary number, to prevent 0's
  285. // from hashing to 0.
  286. h += 0xe6546b64;
  287. }
  288. #endif // BOOST_NO_INT64_T
  289. }
  290. template <typename T>
  291. typename boost::hash_detail::basic_numbers<T>::type hash_value(T v)
  292. {
  293. return static_cast<std::size_t>(v);
  294. }
  295. template <typename T>
  296. typename boost::hash_detail::long_numbers<T>::type hash_value(T v)
  297. {
  298. return hash_detail::hash_value_signed(v);
  299. }
  300. template <typename T>
  301. typename boost::hash_detail::ulong_numbers<T>::type hash_value(T v)
  302. {
  303. return hash_detail::hash_value_unsigned(v);
  304. }
  305. template <typename T>
  306. typename boost::enable_if<boost::is_enum<T>, std::size_t>::type
  307. hash_value(T v)
  308. {
  309. return static_cast<std::size_t>(v);
  310. }
  311. // Implementation by Alberto Barbati and Dave Harris.
  312. #if !BOOST_WORKAROUND(__DMC__, <= 0x848)
  313. template <class T> std::size_t hash_value(T* const& v)
  314. #else
  315. template <class T> std::size_t hash_value(T* v)
  316. #endif
  317. {
  318. #if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
  319. // for some reason ptrdiff_t on OpenVMS compiler with
  320. // 64 bit is not 64 bit !!!
  321. std::size_t x = static_cast<std::size_t>(
  322. reinterpret_cast<long long int>(v));
  323. #else
  324. std::size_t x = static_cast<std::size_t>(
  325. reinterpret_cast<std::ptrdiff_t>(v));
  326. #endif
  327. return x + (x >> 3);
  328. }
  329. #if defined(BOOST_MSVC)
  330. #pragma warning(push)
  331. #if BOOST_MSVC <= 1400
  332. #pragma warning(disable:4267) // 'argument' : conversion from 'size_t' to
  333. // 'unsigned int', possible loss of data
  334. // A misguided attempt to detect 64-bit
  335. // incompatability.
  336. #endif
  337. #endif
  338. template <class T>
  339. inline void hash_combine(std::size_t& seed, T const& v)
  340. {
  341. boost::hash<T> hasher;
  342. return boost::hash_detail::hash_combine_impl(seed, hasher(v));
  343. }
  344. #if defined(BOOST_MSVC)
  345. #pragma warning(pop)
  346. #endif
  347. template <class It>
  348. inline std::size_t hash_range(It first, It last)
  349. {
  350. std::size_t seed = 0;
  351. for(; first != last; ++first)
  352. {
  353. hash_combine(seed, *first);
  354. }
  355. return seed;
  356. }
  357. template <class It>
  358. inline void hash_range(std::size_t& seed, It first, It last)
  359. {
  360. for(; first != last; ++first)
  361. {
  362. hash_combine(seed, *first);
  363. }
  364. }
  365. #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
  366. template <class T>
  367. inline std::size_t hash_range(T* first, T* last)
  368. {
  369. std::size_t seed = 0;
  370. for(; first != last; ++first)
  371. {
  372. boost::hash<T> hasher;
  373. seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
  374. }
  375. return seed;
  376. }
  377. template <class T>
  378. inline void hash_range(std::size_t& seed, T* first, T* last)
  379. {
  380. for(; first != last; ++first)
  381. {
  382. boost::hash<T> hasher;
  383. seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
  384. }
  385. }
  386. #endif
  387. #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  388. template< class T, unsigned N >
  389. inline std::size_t hash_value(const T (&x)[N])
  390. {
  391. return hash_range(x, x + N);
  392. }
  393. template< class T, unsigned N >
  394. inline std::size_t hash_value(T (&x)[N])
  395. {
  396. return hash_range(x, x + N);
  397. }
  398. #endif
  399. template <class Ch, class A>
  400. inline std::size_t hash_value(
  401. std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const& v)
  402. {
  403. return hash_range(v.begin(), v.end());
  404. }
  405. #if BOOST_HASH_HAS_STRING_VIEW
  406. template <class Ch>
  407. inline std::size_t hash_value(
  408. std::basic_string_view<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch> > const& v)
  409. {
  410. return hash_range(v.begin(), v.end());
  411. }
  412. #endif
  413. template <typename T>
  414. typename boost::hash_detail::float_numbers<T>::type hash_value(T v)
  415. {
  416. return boost::hash_detail::float_hash_value(v);
  417. }
  418. #if BOOST_HASH_HAS_OPTIONAL
  419. template <typename T>
  420. inline std::size_t hash_value(std::optional<T> const& v) {
  421. if (!v) {
  422. // Arbitray value for empty optional.
  423. return 0x12345678;
  424. } else {
  425. boost::hash<T> hf;
  426. return hf(*v);
  427. }
  428. }
  429. #endif
  430. #if BOOST_HASH_HAS_VARIANT
  431. inline std::size_t hash_value(std::monostate) {
  432. return 0x87654321;
  433. }
  434. template <typename... Types>
  435. inline std::size_t hash_value(std::variant<Types...> const& v) {
  436. std::size_t seed = 0;
  437. hash_combine(seed, v.index());
  438. std::visit([&seed](auto&& x) { hash_combine(seed, x); }, v);
  439. return seed;
  440. }
  441. #endif
  442. #if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
  443. inline std::size_t hash_value(std::type_index v)
  444. {
  445. return v.hash_code();
  446. }
  447. #endif
  448. #if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
  449. inline std::size_t hash_value(std::error_code const& v) {
  450. std::size_t seed = 0;
  451. hash_combine(seed, v.value());
  452. hash_combine(seed, &v.category());
  453. return seed;
  454. }
  455. inline std::size_t hash_value(std::error_condition const& v) {
  456. std::size_t seed = 0;
  457. hash_combine(seed, v.value());
  458. hash_combine(seed, &v.category());
  459. return seed;
  460. }
  461. #endif
  462. //
  463. // boost::hash
  464. //
  465. // Define the specializations required by the standard. The general purpose
  466. // boost::hash is defined later in extensions.hpp if
  467. // BOOST_HASH_NO_EXTENSIONS is not defined.
  468. // BOOST_HASH_SPECIALIZE - define a specialization for a type which is
  469. // passed by copy.
  470. //
  471. // BOOST_HASH_SPECIALIZE_REF - define a specialization for a type which is
  472. // passed by const reference.
  473. //
  474. // These are undefined later.
  475. #define BOOST_HASH_SPECIALIZE(type) \
  476. template <> struct hash<type> \
  477. : public boost::hash_detail::hash_base<type> \
  478. { \
  479. std::size_t operator()(type v) const \
  480. { \
  481. return boost::hash_value(v); \
  482. } \
  483. };
  484. #define BOOST_HASH_SPECIALIZE_REF(type) \
  485. template <> struct hash<type> \
  486. : public boost::hash_detail::hash_base<type> \
  487. { \
  488. std::size_t operator()(type const& v) const \
  489. { \
  490. return boost::hash_value(v); \
  491. } \
  492. };
  493. #define BOOST_HASH_SPECIALIZE_TEMPLATE_REF(type) \
  494. struct hash<type> \
  495. : public boost::hash_detail::hash_base<type> \
  496. { \
  497. std::size_t operator()(type const& v) const \
  498. { \
  499. return boost::hash_value(v); \
  500. } \
  501. };
  502. BOOST_HASH_SPECIALIZE(bool)
  503. BOOST_HASH_SPECIALIZE(char)
  504. BOOST_HASH_SPECIALIZE(signed char)
  505. BOOST_HASH_SPECIALIZE(unsigned char)
  506. #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  507. BOOST_HASH_SPECIALIZE(wchar_t)
  508. #endif
  509. #if !defined(BOOST_NO_CXX11_CHAR16_T)
  510. BOOST_HASH_SPECIALIZE(char16_t)
  511. #endif
  512. #if !defined(BOOST_NO_CXX11_CHAR32_T)
  513. BOOST_HASH_SPECIALIZE(char32_t)
  514. #endif
  515. BOOST_HASH_SPECIALIZE(short)
  516. BOOST_HASH_SPECIALIZE(unsigned short)
  517. BOOST_HASH_SPECIALIZE(int)
  518. BOOST_HASH_SPECIALIZE(unsigned int)
  519. BOOST_HASH_SPECIALIZE(long)
  520. BOOST_HASH_SPECIALIZE(unsigned long)
  521. BOOST_HASH_SPECIALIZE(float)
  522. BOOST_HASH_SPECIALIZE(double)
  523. BOOST_HASH_SPECIALIZE(long double)
  524. BOOST_HASH_SPECIALIZE_REF(std::string)
  525. #if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  526. BOOST_HASH_SPECIALIZE_REF(std::wstring)
  527. #endif
  528. #if !defined(BOOST_NO_CXX11_CHAR16_T)
  529. BOOST_HASH_SPECIALIZE_REF(std::basic_string<char16_t>)
  530. #endif
  531. #if !defined(BOOST_NO_CXX11_CHAR32_T)
  532. BOOST_HASH_SPECIALIZE_REF(std::basic_string<char32_t>)
  533. #endif
  534. #if BOOST_HASH_HAS_STRING_VIEW
  535. BOOST_HASH_SPECIALIZE_REF(std::string_view)
  536. # if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  537. BOOST_HASH_SPECIALIZE_REF(std::wstring_view)
  538. # endif
  539. # if !defined(BOOST_NO_CXX11_CHAR16_T)
  540. BOOST_HASH_SPECIALIZE_REF(std::basic_string_view<char16_t>)
  541. # endif
  542. # if !defined(BOOST_NO_CXX11_CHAR32_T)
  543. BOOST_HASH_SPECIALIZE_REF(std::basic_string_view<char32_t>)
  544. # endif
  545. #endif
  546. #if !defined(BOOST_NO_LONG_LONG)
  547. BOOST_HASH_SPECIALIZE(boost::long_long_type)
  548. BOOST_HASH_SPECIALIZE(boost::ulong_long_type)
  549. #endif
  550. #if defined(BOOST_HAS_INT128)
  551. BOOST_HASH_SPECIALIZE(boost::int128_type)
  552. BOOST_HASH_SPECIALIZE(boost::uint128_type)
  553. #endif
  554. #if BOOST_HASH_HAS_OPTIONAL
  555. template <typename T>
  556. BOOST_HASH_SPECIALIZE_TEMPLATE_REF(std::optional<T>)
  557. #endif
  558. #if !defined(BOOST_HASH_HAS_VARIANT)
  559. template <typename... T>
  560. BOOST_HASH_SPECIALIZE_TEMPLATE_REF(std::variant<T...>)
  561. BOOST_HASH_SPECIALIZE(std::monostate)
  562. #endif
  563. #if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
  564. BOOST_HASH_SPECIALIZE(std::type_index)
  565. #endif
  566. #undef BOOST_HASH_SPECIALIZE
  567. #undef BOOST_HASH_SPECIALIZE_REF
  568. #undef BOOST_HASH_SPECIALIZE_TEMPLATE_REF
  569. // Specializing boost::hash for pointers.
  570. #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
  571. template <class T>
  572. struct hash<T*>
  573. : public boost::hash_detail::hash_base<T*>
  574. {
  575. std::size_t operator()(T* v) const
  576. {
  577. #if !BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590)
  578. return boost::hash_value(v);
  579. #else
  580. std::size_t x = static_cast<std::size_t>(
  581. reinterpret_cast<std::ptrdiff_t>(v));
  582. return x + (x >> 3);
  583. #endif
  584. }
  585. };
  586. #else
  587. // For compilers without partial specialization, we define a
  588. // boost::hash for all remaining types. But hash_impl is only defined
  589. // for pointers in 'extensions.hpp' - so when BOOST_HASH_NO_EXTENSIONS
  590. // is defined there will still be a compile error for types not supported
  591. // in the standard.
  592. namespace hash_detail
  593. {
  594. template <bool IsPointer>
  595. struct hash_impl;
  596. template <>
  597. struct hash_impl<true>
  598. {
  599. template <class T>
  600. struct inner
  601. : public boost::hash_detail::hash_base<T>
  602. {
  603. std::size_t operator()(T val) const
  604. {
  605. #if !BOOST_WORKAROUND(__SUNPRO_CC, <= 590)
  606. return boost::hash_value(val);
  607. #else
  608. std::size_t x = static_cast<std::size_t>(
  609. reinterpret_cast<std::ptrdiff_t>(val));
  610. return x + (x >> 3);
  611. #endif
  612. }
  613. };
  614. };
  615. }
  616. template <class T> struct hash
  617. : public boost::hash_detail::hash_impl<boost::is_pointer<T>::value>
  618. ::BOOST_NESTED_TEMPLATE inner<T>
  619. {
  620. };
  621. #endif
  622. }
  623. #undef BOOST_HASH_CHAR_TRAITS
  624. #undef BOOST_FUNCTIONAL_HASH_ROTL32
  625. #if defined(BOOST_MSVC)
  626. #pragma warning(pop)
  627. #endif
  628. #endif // BOOST_FUNCTIONAL_HASH_HASH_HPP
  629. // Include this outside of the include guards in case the file is included
  630. // twice - once with BOOST_HASH_NO_EXTENSIONS defined, and then with it
  631. // undefined.
  632. #if !defined(BOOST_HASH_NO_EXTENSIONS) \
  633. && !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP)
  634. #include <boost/container_hash/extensions.hpp>
  635. #endif