42#include <initializer_list>
50#include <system_error>
64# define BOOST_MSVC _MSC_VER
66#elif defined __clang__
70#elif defined(__GNUC__)
72# define BOOST_GCC (__GNUC__ * 10000
+ __GNUC_MINOR__ * 100
+ __GNUC_PATCHLEVEL__)
76#ifndef BOOST_FORCEINLINE
78# define BOOST_FORCEINLINE __forceinline
79# elif defined(__GNUC__
) && __GNUC__
> 3
81# define BOOST_FORCEINLINE inline __attribute__ ((__always_inline__))
83# define BOOST_FORCEINLINE inline
89# define BOOST_NOINLINE __declspec(noinline)
90# elif defined(__GNUC__
) && __GNUC__
> 3
92# if defined(__CUDACC__)
95# define BOOST_NOINLINE __attribute__ ((noinline))
96# elif defined(__HIP__)
98# define BOOST_NOINLINE __attribute__ ((noinline))
100# define BOOST_NOINLINE __attribute__ ((__noinline__))
103# define BOOST_NOINLINE
107#if defined(BOOST_GCC) || defined(BOOST_CLANG
)
108# define BOOST_LIKELY(x) __builtin_expect(x, 1
)
109# define BOOST_UNLIKELY(x) __builtin_expect(x, 0
)
110# define BOOST_SYMBOL_VISIBLE __attribute__((__visibility__("default")))
112# define BOOST_SYMBOL_VISIBLE
116# define BOOST_LIKELY(x) x
119# define BOOST_UNLIKELY(x) x
122#ifndef BOOST_NORETURN
123# if defined(_MSC_VER)
124# define BOOST_NORETURN __declspec(noreturn)
125# elif defined(__GNUC__
) || defined(__CODEGEARC__) && defined(__clang__
)
126# define BOOST_NORETURN __attribute__ ((__noreturn__))
127# elif defined(__has_attribute) && defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x5130
)
128# if __has_attribute(noreturn)
129# define BOOST_NORETURN [[noreturn]]
131# elif defined(__has_cpp_attribute)
132# if __has_cpp_attribute(noreturn)
133# define BOOST_NORETURN [[noreturn]]
139# define BOOST_NO_NORETURN
140# define BOOST_NORETURN
144 #if !defined(_CPPUNWIND) && !defined(BOOST_NO_EXCEPTIONS)
145 #define BOOST_NO_EXCEPTIONS
147 #if !defined(_CPPRTTI) && !defined(BOOST_NO_RTTI)
148 #define BOOST_NO_RTTI
151 #if !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS)
152 #define BOOST_NO_EXCEPTIONS
154 #if !defined(__GXX_RTTI) && !defined(BOOST_NO_RTTI)
155 #define BOOST_NO_RTTI
158 #if !__has_feature
(cxx_exceptions) && !defined(BOOST_NO_EXCEPTIONS)
159 #define BOOST_NO_EXCEPTIONS
161 #if !__has_feature
(cxx_rtti) && !defined(BOOST_NO_RTTI)
162 #define BOOST_NO_RTTI
165#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
166#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED
170#if defined(_MSC_VER) && (_MSC_VER >= 1020
)
192inline void current_function_helper()
195#ifdef BOOST_DISABLE_CURRENT_FUNCTION
197# define BOOST_CURRENT_FUNCTION "(unknown)"
199#elif defined(__GNUC__
) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000
)) || (defined(__ICC) && (__ICC >= 600
)) || defined(__ghs__) || defined(__clang__
)
201# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
203#elif defined(__DMC__) && (__DMC__ >= 0x810
)
205# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
207#elif defined(__FUNCSIG__)
209# define BOOST_CURRENT_FUNCTION __FUNCSIG__
211#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600
)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500
))
213# define BOOST_CURRENT_FUNCTION __FUNCTION__
215#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550
)
217# define BOOST_CURRENT_FUNCTION __FUNC__
219#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901
)
221# define BOOST_CURRENT_FUNCTION __func__
223#elif defined(__cplusplus) && (__cplusplus >= 201103
)
225# define BOOST_CURRENT_FUNCTION __func__
229# define BOOST_CURRENT_FUNCTION "(unknown)"
272#undef BOOST_ASSERT_MSG
273#undef BOOST_ASSERT_IS_VOID
275#if defined(BOOST_DISABLE_ASSERTS) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && defined(NDEBUG) )
277# define BOOST_ASSERT(expr) ((void)0
)
278# define BOOST_ASSERT_MSG(expr, msg) ((void)0
)
279# define BOOST_ASSERT_IS_VOID
281#elif defined(BOOST_ENABLE_ASSERT_HANDLER) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && !defined(NDEBUG) )
285 void assertion_failed(
char const * expr,
char const * function,
char const * file,
long line);
286 void assertion_failed_msg(
char const * expr,
char const * msg,
char const * function,
char const * file,
long line);
289#define BOOST_ASSERT(expr) (BOOST_LIKELY(!!(expr))? ((void)0
): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
290#define BOOST_ASSERT_MSG(expr, msg) (BOOST_LIKELY(!!(expr))? ((void)0
): ::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
296# define BOOST_ASSERT(expr) assert
(expr)
297# define BOOST_ASSERT_MSG(expr, msg) assert
((expr)&&(msg))
299# define BOOST_ASSERT_IS_VOID
309#undef BOOST_VERIFY_MSG
311#if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) )
313# define BOOST_VERIFY(expr) ((void)(expr))
314# define BOOST_VERIFY_MSG(expr, msg) ((void)(expr))
323
324
325
326
327
328
329#ifndef BOOST_CORE_EMPTY_VALUE_HPP
330#define BOOST_CORE_EMPTY_VALUE_HPP
334#pragma warning(disable:4510
)
340struct use_empty_value_base {
342 value =
__is_empty(T) && !
__is_final(T)
346struct empty_init_t { };
350template<
class T,
unsigned N = 0,
351 bool E = boost::use_empty_value_base<T>::value>
356 empty_value() =
default;
358 constexpr empty_value(boost::empty_init_t)
361 template<
class U,
class... Args>
362 constexpr empty_value(boost::empty_init_t, U&& value, Args&&... args)
363 : value_(std::forward<U>(value), std::forward<Args>(args)...) { }
365 constexpr const T& get()
const noexcept {
369 constexpr T& get()
noexcept {
377template<
class T,
unsigned N>
378class empty_value<T, N,
true>
383 empty_value() =
default;
385 constexpr empty_value(boost::empty_init_t)
388 template<
class U,
class... Args>
389 constexpr empty_value(boost::empty_init_t, U&& value, Args&&... args)
390 : T(std::forward<U>(value), std::forward<Args>(args)...) { }
392 constexpr const T& get()
const noexcept {
396 constexpr T& get()
noexcept {
403using empty_::empty_value;
405inline constexpr empty_init_t empty_init = empty_init_t();
414#ifndef BOOST_CORE_NO_EXCEPTIONS_SUPPORT_HPP
415#define BOOST_CORE_NO_EXCEPTIONS_SUPPORT_HPP
436#if !(defined BOOST_NO_EXCEPTIONS)
437# define BOOST_TRY { try
438# define BOOST_CATCH(x) catch(x)
439# define BOOST_RETHROW throw;
440# define BOOST_CATCH_END }
442# if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900
443# define BOOST_TRY { if (true)
444# define BOOST_CATCH(x) else if (false)
448 __pragma(warning(push))
449 __pragma(warning(disable: 4127
))
451 __pragma(warning(pop))
452# define BOOST_CATCH(x) else
453 __pragma(warning(push))
454 __pragma(warning(disable: 4127
))
456 __pragma(warning(pop))
458# define BOOST_RETHROW
459# define BOOST_CATCH_END }
464
465
466
467
468
469
470
471
472
474#ifndef BOOST_UNORDERED_DETAIL_XMX_HPP
475#define BOOST_UNORDERED_DETAIL_XMX_HPP
482
483
484
485
486
487
488
489
490
493#if ((((SIZE_MAX >> 16
) >> 16
) >> 16
) >> 15
) != 0
494#define BOOST_UNORDERED_64B_ARCHITECTURE
496#elif defined(UINTPTR_MAX)
497#if ((((UINTPTR_MAX >> 16
) >> 16
) >> 16
) >> 15
) != 0
498#define BOOST_UNORDERED_64B_ARCHITECTURE
502static inline std::size_t xmx(std::size_t x)
noexcept
504#ifdef BOOST_UNORDERED_64B_ARCHITECTURE
506 std::uint64_t z=(std::uint64_t)x;
509 z*=0xff51afd7ed558ccdull;
512 return (std::size_t)z;
525#ifdef BOOST_UNORDERED_64B_ARCHITECTURE
526#undef BOOST_UNORDERED_64B_ARCHITECTURE
534#ifndef BOOST_UNORDERED_DETAIL_MULX_HPP
535#define BOOST_UNORDERED_DETAIL_MULX_HPP
542#if defined(_MSC_VER) && !defined(__clang__
)
552#if defined(_MSC_VER) && defined(_M_X64) && !defined(__clang__
)
554__forceinline std::uint64_t mulx64( std::uint64_t x, std::uint64_t y )
557 std::uint64_t r = _umul128( x, y, &r2 );
561#elif defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__
)
563__forceinline std::uint64_t mulx64( std::uint64_t x, std::uint64_t y )
565 std::uint64_t r = x * y;
566 std::uint64_t r2 = __umulh( x, y );
570#elif defined(__SIZEOF_INT128__
)
572inline std::uint64_t mulx64( std::uint64_t x, std::uint64_t y )
574 __uint128_t r = (__uint128_t)x * y;
575 return (std::uint64_t)r ^ (std::uint64_t)( r >> 64 );
580inline std::uint64_t mulx64( std::uint64_t x, std::uint64_t y )
582 std::uint64_t x1 = (std::uint32_t)x;
583 std::uint64_t x2 = x >> 32;
585 std::uint64_t y1 = (std::uint32_t)y;
586 std::uint64_t y2 = y >> 32;
588 std::uint64_t r3 = x2 * y2;
590 std::uint64_t r2a = x1 * y2;
594 std::uint64_t r2b = x2 * y1;
598 std::uint64_t r1 = x1 * y1;
600 std::uint64_t r2 = (r1 >> 32) + (std::uint32_t)r2a + (std::uint32_t)r2b;
602 r1 = (r2 << 32) + (std::uint32_t)r1;
610inline std::uint32_t mulx32( std::uint32_t x, std::uint32_t y )
612 std::uint64_t r = (std::uint64_t)x * y;
614#ifdef __MSVC_RUNTIME_CHECKS
616 return (std::uint32_t)(r & UINT32_MAX) ^ (std::uint32_t)(r >> 32);
620 return (std::uint32_t)r ^ (std::uint32_t)(r >> 32);
626#if ((((SIZE_MAX >> 16
) >> 16
) >> 16
) >> 15
) != 0
627#define BOOST_UNORDERED_64B_ARCHITECTURE
629#elif defined(UINTPTR_MAX)
630#if ((((UINTPTR_MAX >> 16
) >> 16
) >> 16
) >> 15
) != 0
631#define BOOST_UNORDERED_64B_ARCHITECTURE
635inline std::size_t mulx( std::size_t x )
noexcept
637#ifdef BOOST_UNORDERED_64B_ARCHITECTURE
640 return (std::size_t)mulx64( (std::uint64_t)x, 0x9E3779B97F4A7C15ull );
645 return mulx32( x, 0xE817FB2Du );
650#ifdef BOOST_UNORDERED_64B_ARCHITECTURE
651#undef BOOST_UNORDERED_64B_ARCHITECTURE
660
661
662
663
664
665
666
667
669#ifndef BOOST_UNORDERED_HASH_TRAITS_HPP
670#define BOOST_UNORDERED_HASH_TRAITS_HPP
677template<
typename Hash,
typename=
void>
678struct hash_is_avalanching_impl: std::false_type{};
680template<
typename Hash>
681struct hash_is_avalanching_impl<Hash,
682 typename std::void_t<
typename Hash::is_avalanching>>:
688
689
692
693
694template<
typename Hash>
695struct hash_is_avalanching: detail::hash_is_avalanching_impl<Hash>::type{};
702
703
704
705
706
707
708
709
710
712#ifndef BOOST_UNORDERED_DETAIL_FOA_HPP
713#define BOOST_UNORDERED_DETAIL_FOA_HPP
715#ifndef BOOST_UNORDERED_DISABLE_SSE2
716#if defined(BOOST_UNORDERED_ENABLE_SSE2)||
718 defined(_M_X64)||(defined(_M_IX86_FP)&&_M_IX86_FP>=2
)
719#define BOOST_UNORDERED_SSE2
723#ifndef BOOST_UNORDERED_DISABLE_NEON
724#if defined(BOOST_UNORDERED_ENABLE_NEON)||
725 (defined(__ARM_NEON)&&!defined(__ARM_BIG_ENDIAN))
726#define BOOST_UNORDERED_LITTLE_ENDIAN_NEON
730#ifdef BOOST_UNORDERED_SSE2
731#include <emmintrin.h>
732#elif defined(BOOST_UNORDERED_LITTLE_ENDIAN_NEON)
737#define BOOST_UNORDERED_HAS_BUILTIN(x) __has_builtin(x)
739#define BOOST_UNORDERED_HAS_BUILTIN(x) 0
744#elif BOOST_UNORDERED_HAS_BUILTIN(__builtin_assume)
745#define BOOST_UNORDERED_ASSUME(cond) __builtin_assume(cond)
746#elif defined(__GNUC__) || BOOST_UNORDERED_HAS_BUILTIN(__builtin_unreachable)
747#define BOOST_UNORDERED_ASSUME(cond)
749 if(!(cond))__builtin_unreachable();
751#elif defined(_MSC_VER)
752#define BOOST_UNORDERED_ASSUME(cond) __assume(cond)
754#define BOOST_UNORDERED_ASSUME(cond)
756 static_cast<void>(false&&(cond));
760#define BOOST_UNORDERED_STATIC_ASSERT_HASH_PRED(Hash, Pred)
761 static_assert(std::is_nothrow_swappable<Hash>::value,
762 "Template parameter Hash is required to be nothrow Swappable.");
763 static_assert(std::is_nothrow_swappable<Pred>::value,
764 "Template parameter Pred is required to be nothrow Swappable");
769 defined(__ARM_ARCH) || defined(__TARGET_ARCH_ARM) ||
770 defined(__TARGET_ARCH_THUMB) || defined(_M_ARM) ||
771 defined(__arm__) || defined(__arm64) || defined(__thumb__) ||
772 defined(_M_ARM64) || defined(__aarch64__) || defined(__AARCH64EL__) ||
773 defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) ||
774 defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) ||
775 defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) ||
776 defined(__ARM_ARCH_6KZ__) || defined(__ARM_ARCH_6T2__) ||
777 defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__) ||
778 defined(__ARM_ARCH_4T__) || defined(__ARM_ARCH_4__)
779#define BOOST_ARCH_ARM 1
781#define BOOST_ARCH_ARM 0
789static const std::size_t default_bucket_count = 0;
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
850#ifdef BOOST_UNORDERED_SSE2
854 static constexpr int N=15;
856 struct dummy_group_type
858 alignas(16)
unsigned char storage[N+1]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0};
861 inline void initialize(){m=_mm_setzero_si128();}
863 inline void set(std::size_t pos,std::size_t hash)
866 at(pos)=reduced_hash(hash);
869 inline void set_sentinel()
874 inline bool is_sentinel(std::size_t pos)
const
877 return at(pos)==sentinel_;
880 inline void reset(std::size_t pos)
886 static inline void reset(
unsigned char* pc)
891 inline int match(std::size_t hash)
const
893 return _mm_movemask_epi8(
894 _mm_cmpeq_epi8(m,_mm_set1_epi32(match_word(hash))))&0x7FFF;
897 inline bool is_not_overflowed(std::size_t hash)
const
899 static constexpr unsigned char shift[]={1,2,4,8,16,32,64,128};
901 return !(overflow()&shift[hash%8]);
904 inline void mark_overflow(std::size_t hash)
906 overflow()|=
static_cast<
unsigned char>(1<<(hash%8));
909 static inline bool maybe_caused_overflow(
unsigned char* pc)
911 std::size_t pos=
reinterpret_cast<uintptr_t>(pc)%
sizeof(group15);
912 group15 *pg=
reinterpret_cast<group15*>(pc-pos);
913 return !pg->is_not_overflowed(*pc);
916 inline int match_available()
const
918 return _mm_movemask_epi8(
919 _mm_cmpeq_epi8(m,_mm_setzero_si128()))&0x7FFF;
922 inline int match_occupied()
const
924 return (~match_available())&0x7FFF;
927 inline int match_really_occupied()
const
929 return at(N-1)==sentinel_?match_occupied()&0x3FFF:match_occupied();
933 static constexpr unsigned char available_=0,
936 inline static int match_word(std::size_t hash)
938 static constexpr std::uint32_t word[]=
940 0x08080808u,0x09090909u,0x02020202u,0x03030303u,0x04040404u,0x05050505u,0x06060606u,0x07070707u,
941 0x08080808u,0x09090909u,0x0A0A0A0Au,0x0B0B0B0Bu,0x0C0C0C0Cu,0x0D0D0D0Du,0x0E0E0E0Eu,0x0F0F0F0Fu,
942 0x10101010u,0x11111111u,0x12121212u,0x13131313u,0x14141414u,0x15151515u,0x16161616u,0x17171717u,
943 0x18181818u,0x19191919u,0x1A1A1A1Au,0x1B1B1B1Bu,0x1C1C1C1Cu,0x1D1D1D1Du,0x1E1E1E1Eu,0x1F1F1F1Fu,
944 0x20202020u,0x21212121u,0x22222222u,0x23232323u,0x24242424u,0x25252525u,0x26262626u,0x27272727u,
945 0x28282828u,0x29292929u,0x2A2A2A2Au,0x2B2B2B2Bu,0x2C2C2C2Cu,0x2D2D2D2Du,0x2E2E2E2Eu,0x2F2F2F2Fu,
946 0x30303030u,0x31313131u,0x32323232u,0x33333333u,0x34343434u,0x35353535u,0x36363636u,0x37373737u,
947 0x38383838u,0x39393939u,0x3A3A3A3Au,0x3B3B3B3Bu,0x3C3C3C3Cu,0x3D3D3D3Du,0x3E3E3E3Eu,0x3F3F3F3Fu,
948 0x40404040u,0x41414141u,0x42424242u,0x43434343u,0x44444444u,0x45454545u,0x46464646u,0x47474747u,
949 0x48484848u,0x49494949u,0x4A4A4A4Au,0x4B4B4B4Bu,0x4C4C4C4Cu,0x4D4D4D4Du,0x4E4E4E4Eu,0x4F4F4F4Fu,
950 0x50505050u,0x51515151u,0x52525252u,0x53535353u,0x54545454u,0x55555555u,0x56565656u,0x57575757u,
951 0x58585858u,0x59595959u,0x5A5A5A5Au,0x5B5B5B5Bu,0x5C5C5C5Cu,0x5D5D5D5Du,0x5E5E5E5Eu,0x5F5F5F5Fu,
952 0x60606060u,0x61616161u,0x62626262u,0x63636363u,0x64646464u,0x65656565u,0x66666666u,0x67676767u,
953 0x68686868u,0x69696969u,0x6A6A6A6Au,0x6B6B6B6Bu,0x6C6C6C6Cu,0x6D6D6D6Du,0x6E6E6E6Eu,0x6F6F6F6Fu,
954 0x70707070u,0x71717171u,0x72727272u,0x73737373u,0x74747474u,0x75757575u,0x76767676u,0x77777777u,
955 0x78787878u,0x79797979u,0x7A7A7A7Au,0x7B7B7B7Bu,0x7C7C7C7Cu,0x7D7D7D7Du,0x7E7E7E7Eu,0x7F7F7F7Fu,
956 0x80808080u,0x81818181u,0x82828282u,0x83838383u,0x84848484u,0x85858585u,0x86868686u,0x87878787u,
957 0x88888888u,0x89898989u,0x8A8A8A8Au,0x8B8B8B8Bu,0x8C8C8C8Cu,0x8D8D8D8Du,0x8E8E8E8Eu,0x8F8F8F8Fu,
958 0x90909090u,0x91919191u,0x92929292u,0x93939393u,0x94949494u,0x95959595u,0x96969696u,0x97979797u,
959 0x98989898u,0x99999999u,0x9A9A9A9Au,0x9B9B9B9Bu,0x9C9C9C9Cu,0x9D9D9D9Du,0x9E9E9E9Eu,0x9F9F9F9Fu,
960 0xA0A0A0A0u,0xA1A1A1A1u,0xA2A2A2A2u,0xA3A3A3A3u,0xA4A4A4A4u,0xA5A5A5A5u,0xA6A6A6A6u,0xA7A7A7A7u,
961 0xA8A8A8A8u,0xA9A9A9A9u,0xAAAAAAAAu,0xABABABABu,0xACACACACu,0xADADADADu,0xAEAEAEAEu,0xAFAFAFAFu,
962 0xB0B0B0B0u,0xB1B1B1B1u,0xB2B2B2B2u,0xB3B3B3B3u,0xB4B4B4B4u,0xB5B5B5B5u,0xB6B6B6B6u,0xB7B7B7B7u,
963 0xB8B8B8B8u,0xB9B9B9B9u,0xBABABABAu,0xBBBBBBBBu,0xBCBCBCBCu,0xBDBDBDBDu,0xBEBEBEBEu,0xBFBFBFBFu,
964 0xC0C0C0C0u,0xC1C1C1C1u,0xC2C2C2C2u,0xC3C3C3C3u,0xC4C4C4C4u,0xC5C5C5C5u,0xC6C6C6C6u,0xC7C7C7C7u,
965 0xC8C8C8C8u,0xC9C9C9C9u,0xCACACACAu,0xCBCBCBCBu,0xCCCCCCCCu,0xCDCDCDCDu,0xCECECECEu,0xCFCFCFCFu,
966 0xD0D0D0D0u,0xD1D1D1D1u,0xD2D2D2D2u,0xD3D3D3D3u,0xD4D4D4D4u,0xD5D5D5D5u,0xD6D6D6D6u,0xD7D7D7D7u,
967 0xD8D8D8D8u,0xD9D9D9D9u,0xDADADADAu,0xDBDBDBDBu,0xDCDCDCDCu,0xDDDDDDDDu,0xDEDEDEDEu,0xDFDFDFDFu,
968 0xE0E0E0E0u,0xE1E1E1E1u,0xE2E2E2E2u,0xE3E3E3E3u,0xE4E4E4E4u,0xE5E5E5E5u,0xE6E6E6E6u,0xE7E7E7E7u,
969 0xE8E8E8E8u,0xE9E9E9E9u,0xEAEAEAEAu,0xEBEBEBEBu,0xECECECECu,0xEDEDEDEDu,0xEEEEEEEEu,0xEFEFEFEFu,
970 0xF0F0F0F0u,0xF1F1F1F1u,0xF2F2F2F2u,0xF3F3F3F3u,0xF4F4F4F4u,0xF5F5F5F5u,0xF6F6F6F6u,0xF7F7F7F7u,
971 0xF8F8F8F8u,0xF9F9F9F9u,0xFAFAFAFAu,0xFBFBFBFBu,0xFCFCFCFCu,0xFDFDFDFDu,0xFEFEFEFEu,0xFFFFFFFFu,
974 return (
int)word[
static_cast<
unsigned char>(hash)];
977 inline static unsigned char reduced_hash(std::size_t hash)
979 return static_cast<
unsigned char>(match_word(hash));
982 inline unsigned char& at(std::size_t pos)
984 return reinterpret_cast<
unsigned char*>(&m)[pos];
987 inline unsigned char at(std::size_t pos)
const
989 return reinterpret_cast<
const unsigned char*>(&m)[pos];
992 inline unsigned char& overflow()
997 inline unsigned char overflow()
const
1002 alignas(16) __m128i m;
1005#elif defined(BOOST_UNORDERED_LITTLE_ENDIAN_NEON)
1009 static constexpr int N=15;
1011 struct dummy_group_type
1013 alignas(16)
unsigned char storage[N+1]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0};
1016 inline void initialize(){m=vdupq_n_s8(0);}
1018 inline void set(std::size_t pos,std::size_t hash)
1020 BOOST_ASSERT(pos<N);
1021 at(pos)=reduced_hash(hash);
1024 inline void set_sentinel()
1029 inline bool is_sentinel(std::size_t pos)
const
1031 BOOST_ASSERT(pos<N);
1032 return pos==N-1&&at(N-1)==sentinel_;
1035 inline void reset(std::size_t pos)
1037 BOOST_ASSERT(pos<N);
1041 static inline void reset(
unsigned char* pc)
1046 inline int match(std::size_t hash)
const
1048 return simde_mm_movemask_epi8(vceqq_s8(
1049 m,vdupq_n_s8(
static_cast<
signed char>(reduced_hash(hash)))))&0x7FFF;
1052 inline bool is_not_overflowed(std::size_t hash)
const
1054 static constexpr unsigned char shift[]={1,2,4,8,16,32,64,128};
1056 return !(overflow()&shift[hash%8]);
1059 inline void mark_overflow(std::size_t hash)
1061 overflow()|=
static_cast<
unsigned char>(1<<(hash%8));
1064 static inline bool maybe_caused_overflow(
unsigned char* pc)
1066 std::size_t pos=
reinterpret_cast<uintptr_t>(pc)%
sizeof(group15);
1067 group15 *pg=
reinterpret_cast<group15*>(pc-pos);
1068 return !pg->is_not_overflowed(*pc);
1071 inline int match_available()
const
1073 return simde_mm_movemask_epi8(vceqq_s8(m,vdupq_n_s8(0)))&0x7FFF;
1076 inline int match_occupied()
const
1078 return simde_mm_movemask_epi8(
1079 vcgtq_u8(vreinterpretq_u8_s8(m),vdupq_n_u8(0)))&0x7FFF;
1082 inline int match_really_occupied()
const
1084 return at(N-1)==sentinel_?match_occupied()&0x3FFF:match_occupied();
1088 static constexpr unsigned char available_=0,
1091 inline static unsigned char reduced_hash(std::size_t hash)
1093 static constexpr unsigned char table[]={
1094 8,9,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
1095 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
1096 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
1097 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
1098 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
1099 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
1100 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
1101 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
1102 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
1103 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
1104 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
1105 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
1106 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
1107 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
1108 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
1109 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
1112 return table[(
unsigned char)hash];
1116
1117
1119 static inline int simde_mm_movemask_epi8(uint8x16_t a)
1121 static constexpr uint8_t md[16]={
1122 1 << 0, 1 << 1, 1 << 2, 1 << 3,
1123 1 << 4, 1 << 5, 1 << 6, 1 << 7,
1124 1 << 0, 1 << 1, 1 << 2, 1 << 3,
1125 1 << 4, 1 << 5, 1 << 6, 1 << 7,
1128 uint8x16_t masked=vandq_u8(vld1q_u8(md),a);
1129 uint8x8x2_t tmp=vzip_u8(vget_low_u8(masked),vget_high_u8(masked));
1130 uint16x8_t x=vreinterpretq_u16_u8(vcombine_u8(tmp.val[0],tmp.val[1]));
1132#ifdef __ARM_ARCH_ISA_A64
1133 return vaddvq_u16(x);
1135 uint64x2_t t64=vpaddlq_u32(vpaddlq_u16(x));
1136 return int(vgetq_lane_u64(t64,0))+
int(vgetq_lane_u64(t64,1));
1140 inline unsigned char& at(std::size_t pos)
1142 return reinterpret_cast<
unsigned char*>(&m)[pos];
1145 inline unsigned char at(std::size_t pos)
const
1147 return reinterpret_cast<
const unsigned char*>(&m)[pos];
1150 inline unsigned char& overflow()
1155 inline unsigned char overflow()
const
1160 alignas(16) int8x16_t m;
1167 static constexpr int N=15;
1169 struct dummy_group_type
1171 alignas(16) std::uint64_t m[2]=
1172 {0x0000000000004000ull,0x0000000000000000ull};
1175 inline void initialize(){m[0]=0;m[1]=0;}
1177 inline void set(std::size_t pos,std::size_t hash)
1179 BOOST_ASSERT(pos<N);
1180 set_impl(pos,reduced_hash(hash));
1183 inline void set_sentinel()
1185 set_impl(N-1,sentinel_);
1188 inline bool is_sentinel(std::size_t pos)
const
1190 BOOST_ASSERT(pos<N);
1193 (m[0] & std::uint64_t(0x4000400040004000ull))==std::uint64_t(0x4000ull)&&
1194 (m[1] & std::uint64_t(0x4000400040004000ull))==0;
1197 inline void reset(std::size_t pos)
1199 BOOST_ASSERT(pos<N);
1200 set_impl(pos,available_);
1203 static inline void reset(
unsigned char* pc)
1205 std::size_t pos=
reinterpret_cast<uintptr_t>(pc)%
sizeof(group15);
1207 reinterpret_cast<group15*>(pc)->reset(pos);
1210 inline int match(std::size_t hash)
const
1212 return match_impl(reduced_hash(hash));
1215 inline bool is_not_overflowed(std::size_t hash)
const
1217 return !(
reinterpret_cast<
const std::uint16_t*>(m)[hash%8] & 0x8000u);
1220 inline void mark_overflow(std::size_t hash)
1222 reinterpret_cast<std::uint16_t*>(m)[hash%8]|=0x8000u;
1225 static inline bool maybe_caused_overflow(
unsigned char* pc)
1227 std::size_t pos=
reinterpret_cast<uintptr_t>(pc)%
sizeof(group15);
1228 group15 *pg=
reinterpret_cast<group15*>(pc-pos);
1229 std::uint64_t x=((pg->m[0])>>pos)&0x000100010001ull;
1230 std::uint32_t y=
static_cast<std::uint32_t>(x|(x>>15)|(x>>30));
1231 return !pg->is_not_overflowed(y);
1234 inline int match_available()
const
1236 std::uint64_t x=~(m[0]|m[1]);
1237 std::uint32_t y=
static_cast<std::uint32_t>(x&(x>>32));
1242 inline int match_occupied()
const
1244 std::uint64_t x=m[0]|m[1];
1245 std::uint32_t y=
static_cast<std::uint32_t>(x|(x>>32));
1250 inline int match_really_occupied()
const
1252 return ~(match_impl(0)|match_impl(1))&0x7FFF;
1256 static constexpr unsigned char available_=0,
1259 inline static unsigned char reduced_hash(std::size_t hash)
1261 static constexpr unsigned char table[]={
1262 8,9,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
1263 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
1264 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
1265 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
1266 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
1267 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
1268 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
1269 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
1270 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
1271 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
1272 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
1273 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
1274 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
1275 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
1276 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
1277 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
1280 return table[
static_cast<
unsigned char>(hash)];
1283 inline void set_impl(std::size_t pos,std::size_t n)
1285 BOOST_ASSERT(n<256);
1286 set_impl(m[0],pos,n&0xFu);
1287 set_impl(m[1],pos,n>>4);
1290 static inline void set_impl(std::uint64_t& x,std::size_t pos,std::size_t n)
1292 static constexpr std::uint64_t mask[]=
1294 0x0000000000000000ull,0x0000000000000001ull,0x0000000000010000ull,
1295 0x0000000000010001ull,0x0000000100000000ull,0x0000000100000001ull,
1296 0x0000000100010000ull,0x0000000100010001ull,0x0001000000000000ull,
1297 0x0001000000000001ull,0x0001000000010000ull,0x0001000000010001ull,
1298 0x0001000100000000ull,0x0001000100000001ull,0x0001000100010000ull,
1299 0x0001000100010001ull,
1301 static constexpr std::uint64_t imask[]=
1303 0x0001000100010001ull,0x0001000100010000ull,0x0001000100000001ull,
1304 0x0001000100000000ull,0x0001000000010001ull,0x0001000000010000ull,
1305 0x0001000000000001ull,0x0001000000000000ull,0x0000000100010001ull,
1306 0x0000000100010000ull,0x0000000100000001ull,0x0000000100000000ull,
1307 0x0000000000010001ull,0x0000000000010000ull,0x0000000000000001ull,
1308 0x0000000000000000ull,
1311 BOOST_ASSERT(pos<16&&n<16);
1313 x&=~(imask[n]<<pos);
1316 inline int match_impl(std::size_t n)
const
1318 static constexpr std::uint64_t mask[]=
1320 0x0000000000000000ull,0x000000000000ffffull,0x00000000ffff0000ull,
1321 0x00000000ffffffffull,0x0000ffff00000000ull,0x0000ffff0000ffffull,
1322 0x0000ffffffff0000ull,0x0000ffffffffffffull,0xffff000000000000ull,
1323 0xffff00000000ffffull,0xffff0000ffff0000ull,0xffff0000ffffffffull,
1324 0xffffffff00000000ull,0xffffffff0000ffffull,0xffffffffffff0000ull,
1325 0xffffffffffffffffull,
1328 BOOST_ASSERT(n<256);
1329 std::uint64_t x=m[0]^mask[n&0xFu];
1330 x=~((m[1]^mask[n>>4])|x);
1331 std::uint32_t y=
static_cast<std::uint32_t>(x&(x>>32));
1336 alignas(16) std::uint64_t m[2];
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1369struct pow2_size_policy
1371 static inline std::size_t size_index(std::size_t n)
1376 return sizeof(std::size_t)*CHAR_BIT-
1377 (n<=2?1:((std::size_t)(std::bit_width(n-1))));
1380 static inline std::size_t size(std::size_t size_index_)
1382 return std::size_t(1)<<(
sizeof(std::size_t)*CHAR_BIT-size_index_);
1385 static constexpr std::size_t min_size(){
return 2;}
1387 static inline std::size_t position(std::size_t hash,std::size_t size_index_)
1389 return hash>>size_index_;
1395template<
typename Group,
typename SizePolicy>
1396static inline std::size_t size_index_for(std::size_t n)
1399 return SizePolicy::size_index(n/Group::N+1);
1403
1404
1405
1407struct pow2_quadratic_prober
1409 pow2_quadratic_prober(std::size_t pos_):pos{pos_}{}
1411 inline std::size_t get()
const{
return pos;}
1414
1415
1416
1418 inline bool next(std::size_t mask)
1421 pos=(pos+step)&mask;
1426 std::size_t pos,step=0;
1430
1431
1432
1433
1434
1435
1439 template<
typename Hash,
typename T>
1440 static inline std::size_t mix(
const Hash& h,
const T& x)
1448 template<
typename Hash,
typename T>
1449 static inline std::size_t mix(
const Hash& h,
const T& x)
1457 template<
typename Hash,
typename T>
1458 static inline std::size_t mix(
const Hash& h,
const T& x)
1465
1466
1468inline unsigned int unchecked_countr_zero(
int x)
1472 _BitScanForward(&r,(
unsigned long)x);
1473 return (
unsigned int)r;
1476 return (
unsigned int)std::countr_zero((
unsigned int)x);
1480template<
typename,
typename,
typename,
typename>
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1506class const_iterator_cast_tag {};
1508template<
typename TypePolicy,
typename Group,
bool Const>
1511 using type_policy=TypePolicy;
1512 using table_element_type=
typename type_policy::element_type;
1515 using difference_type=std::ptrdiff_t;
1516 using value_type=
typename type_policy::value_type;
1518 typename std::conditional<Const,value_type
const*,value_type*>::type;
1520 typename std::conditional<Const,value_type
const&,value_type&>::type;
1521 using iterator_category=std::forward_iterator_tag;
1523 typename std::conditional<Const,value_type
const,value_type>::type;
1525 table_iterator()=
default;
1526 template<
bool Const2,
typename std::enable_if<!Const2>::type* =
nullptr>
1527 table_iterator(
const table_iterator<TypePolicy,Group,Const2>& x):
1530 const_iterator_cast_tag,
const table_iterator<TypePolicy,Group,
true>& x):
1533 inline reference operator*()
const noexcept{
return type_policy::value_from(*p);}
1534 inline pointer operator->()
const noexcept
1535 {
return std::addressof(type_policy::value_from(*p));}
1536 inline table_iterator& operator++()
noexcept{increment();
return *
this;}
1537 inline table_iterator operator++(
int)
noexcept
1538 {
auto x=*
this;increment();
return x;}
1539 friend inline bool operator==(
1540 const table_iterator& x,
const table_iterator& y)
1542 friend inline bool operator!=(
1543 const table_iterator& x,
const table_iterator& y)
1547 template<
typename,
typename,
bool>
friend class table_iterator;
1548 template<
typename,
typename,
typename,
typename>
friend class table;
1550 table_iterator(Group* pg,std::size_t n,
const table_element_type* p_):
1551 pc{
reinterpret_cast<
unsigned char*>(
const_cast<Group*>(pg))+n},
1552 p{
const_cast<table_element_type*>(p_)}
1555 inline std::size_t rebase()
noexcept
1557 std::size_t off=
reinterpret_cast<uintptr_t>(pc)%
sizeof(Group);
1562 inline void increment()
noexcept
1564 std::size_t n0=rebase();
1566 int mask=(
reinterpret_cast<Group*>(pc)->match_occupied()>>(n0+1))<<(n0+1);
1572 while((mask=
reinterpret_cast<Group*>(pc)->match_occupied())==0);
1575 auto n=unchecked_countr_zero(mask);
1576 if(
BOOST_UNLIKELY(
reinterpret_cast<Group*>(pc)->is_sentinel(n))){
1586 unsigned char *pc=
nullptr;
1587 table_element_type *p=
nullptr;
1591
1592
1593
1594
1595
1596
1597
1599template<
typename Group,std::size_t Size>
1600Group* dummy_groups()
1603
1604
1605
1606
1607
1608
1610 static constexpr typename Group::dummy_group_type
1611 storage[Size]={
typename Group::dummy_group_type(),};
1613 return reinterpret_cast<Group*>(
1614 const_cast<
typename Group::dummy_group_type*>(storage));
1617template<
typename Value,
typename Group,
typename SizePolicy>
1620 using value_type=Value;
1621 using group_type=Group;
1622 static constexpr auto N=group_type::N;
1623 using size_policy=SizePolicy;
1625 template<
typename Allocator>
1626 static table_arrays new_(Allocator& al,std::size_t n)
1628 using storage_allocator=
1629 typename std::allocator_traits<Allocator>::
template rebind_alloc<Value>;
1630 using storage_traits=std::allocator_traits<storage_allocator>;
1632 auto groups_size_index=size_index_for<group_type,size_policy>(n);
1633 auto groups_size=size_policy::size(groups_size_index);
1634 table_arrays arrays{groups_size_index,groups_size-1,
nullptr,
nullptr};
1637 arrays.groups=dummy_groups<group_type,size_policy::min_size()>();
1640 auto sal=storage_allocator(al);
1641 arrays.elements=std::to_address(
1642 storage_traits::allocate(sal,buffer_size(groups_size)));
1645
1646
1648 auto p=
reinterpret_cast<
unsigned char*>(arrays.elements+groups_size*N-1);
1649 p+=(uintptr_t(
sizeof(group_type))-
1650 reinterpret_cast<uintptr_t>(p))%
sizeof(group_type);
1651 arrays.groups=
reinterpret_cast<group_type*>(p);
1654
1655
1657 std::memset(arrays.groups,0,
sizeof(group_type)*groups_size);
1658 arrays.groups[groups_size-1].set_sentinel();
1663 template<
typename Allocator>
1664 static void delete_(Allocator& al,table_arrays& arrays)
noexcept
1666 using storage_alloc=
typename std::allocator_traits<Allocator>::
template rebind_alloc<Value>;
1667 using storage_traits=std::allocator_traits<storage_alloc>;
1668 using pointer=
typename storage_traits::pointer;
1669 using pointer_traits=std::pointer_traits<pointer>;
1671 auto sal=storage_alloc(al);
1672 if(arrays.elements){
1673 storage_traits::deallocate(
1674 sal,pointer_traits::pointer_to(*arrays.elements),
1675 buffer_size(arrays.groups_size_mask+1));
1681 static std::size_t buffer_size(std::size_t groups_size)
1685 sizeof(value_type)*(groups_size*N-1)+
1687 sizeof(group_type)*(groups_size+1)-1;
1690 return (buffer_bytes+
sizeof(value_type)-1)/
sizeof(value_type);
1693 std::size_t groups_size_index;
1694 std::size_t groups_size_mask;
1696 value_type *elements;
1699struct if_constexpr_void_else{
void operator()()
const{}};
1701template<
bool B,
typename F,
typename G=if_constexpr_void_else>
1702void if_constexpr(F f,G g={})
1704 std::get<B?0:1>(std::forward_as_tuple(f,g))();
1707template<
bool B,
typename T,
typename std::enable_if<B>::type* =
nullptr>
1708void copy_assign_if(T& x,
const T& y){x=y;}
1710template<
bool B,
typename T,
typename std::enable_if<!B>::type* =
nullptr>
1711void copy_assign_if(T&,
const T&){}
1713template<
bool B,
typename T,
typename std::enable_if<B>::type* =
nullptr>
1714void move_assign_if(T& x,T& y){x=std::move(y);}
1716template<
bool B,
typename T,
typename std::enable_if<!B>::type* =
nullptr>
1717void move_assign_if(T&,T&){}
1719template<
bool B,
typename T,
typename std::enable_if<B>::type* =
nullptr>
1720void swap_if(T& x,T& y){
using std::swap; swap(x,y);}
1722template<
bool B,
typename T,
typename std::enable_if<!B>::type* =
nullptr>
1723void swap_if(T&,T&){}
1725inline void prefetch(
const void* p)
1728#if defined(BOOST_GCC)||defined(BOOST_CLANG
)
1729 __builtin_prefetch((
const char*)p);
1730#elif defined(BOOST_UNORDERED_SSE2)
1731 _mm_prefetch((
const char*)p,_MM_HINT_T0);
1735struct try_emplace_args_t{};
1737template<
typename Allocator>
1738struct is_std_allocator:std::false_type{};
1741struct is_std_allocator<std::allocator<T>>:std::true_type{};
1744#ifdef _LIBCPP_SUPPRESS_DEPRECATED_PUSH
1745_LIBCPP_SUPPRESS_DEPRECATED_PUSH
1746#elif defined(_STL_DISABLE_DEPRECATED_WARNING)
1747_STL_DISABLE_DEPRECATED_WARNING
1748#elif defined(_MSC_VER)
1749#pragma warning(push)
1750#pragma warning(disable:4996
)
1753template<
typename Allocator,
typename Ptr,
typename... Args>
1754struct alloc_has_construct
1757 template<
typename Allocator2>
1759 std::declval<Allocator2&>().construct(
1760 std::declval<Ptr>(),std::declval<Args&&>()...),
1764 template<
typename>
static std::false_type check(...);
1767 static constexpr bool value=
decltype(check<Allocator>(0))::value;
1770#ifdef _LIBCPP_SUPPRESS_DEPRECATED_POP
1771_LIBCPP_SUPPRESS_DEPRECATED_POP
1772#elif defined(_STL_RESTORE_DEPRECATED_WARNING)
1773_STL_RESTORE_DEPRECATED_WARNING
1774#elif defined(_MSC_VER)
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1796#pragma GCC diagnostic push
1797#pragma GCC diagnostic ignored "-Wshadow"
1801#pragma warning(push)
1802#pragma warning(disable:4714
)
1806
1807
1808
1809constexpr static float const mlf = 0.875f;
1812union uninitialized_storage
1815 uninitialized_storage(){}
1816 ~uninitialized_storage(){}
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1884template<
typename TypePolicy,
typename Hash,
typename Pred,
typename Allocator>
1887#if defined(_MSC_VER)&&_MSC_FULL_VER>=190023918
1888__declspec(empty_bases)
1891table:empty_value<Hash,0>,empty_value<Pred,1>,empty_value<Allocator,2>
1893 using hash_base=empty_value<Hash,0>;
1894 using pred_base=empty_value<Pred,1>;
1895 using allocator_base=empty_value<Allocator,2>;
1896 using type_policy=TypePolicy;
1897 using group_type=group15;
1898 static constexpr auto N=group_type::N;
1899 using size_policy=pow2_size_policy;
1900 using prober=pow2_quadratic_prober;
1901 using mix_policy=
typename std::conditional<
1902 hash_is_avalanching<Hash>::value,
1906 using alloc_traits=std::allocator_traits<Allocator>;
1909 using key_type=
typename type_policy::key_type;
1910 using init_type=
typename type_policy::init_type;
1911 using value_type=
typename type_policy::value_type;
1912 using element_type=
typename type_policy::element_type;
1915 static constexpr bool has_mutable_iterator=
1916 !std::is_same<key_type,value_type>::value;
1920 using key_equal=Pred;
1921 using allocator_type=Allocator;
1922 using pointer=value_type*;
1923 using const_pointer=
const value_type*;
1924 using reference=value_type&;
1925 using const_reference=
const value_type&;
1926 using size_type=std::size_t;
1927 using difference_type=std::ptrdiff_t;
1928 using const_iterator=table_iterator<type_policy,group_type,
true>;
1929 using iterator=
typename std::conditional<
1930 has_mutable_iterator,
1931 table_iterator<type_policy,group_type,
false>,
1932 const_iterator>::type;
1935 std::size_t n=0,
const Hash& h_=Hash(),
const Pred& pred_=Pred(),
1936 const Allocator& al_=Allocator()):
1937 hash_base{empty_init,h_},pred_base{empty_init,pred_},
1938 allocator_base{empty_init,al_},size_{0},arrays(new_arrays(n)),
1939 ml{initial_max_load()}
1942 table(
const table& x):
1943 table{x,alloc_traits::select_on_container_copy_construction(x.al())}{}
1947 std::is_nothrow_move_constructible<Hash>::value&&
1948 std::is_nothrow_move_constructible<Pred>::value&&
1949 std::is_nothrow_move_constructible<Allocator>::value):
1950 hash_base{empty_init,std::move(x.h())},
1951 pred_base{empty_init,std::move(x.pred())},
1952 allocator_base{empty_init,std::move(x.al())},
1953 size_{x.size_},arrays(x.arrays),ml{x.ml}
1956 x.arrays=x.new_arrays(0);
1957 x.ml=x.initial_max_load();
1960 table(
const table& x,
const Allocator& al_):
1961 table{std::size_t(std::ceil(
float(x.size())/mlf)),x.h(),x.pred(),al_}
1963 copy_elements_from(x);
1966 table(table&& x,
const Allocator& al_):
1967 table{0,std::move(x.h()),std::move(x.pred()),al_}
1970 std::swap(size_,x.size_);
1971 std::swap(arrays,x.arrays);
1980
1981
1982 x.for_all_elements([
this](element_type* p){
1983 unchecked_insert(type_policy::move(type_policy::value_from(*p)));
1990 for_all_elements([
this](element_type* p){
1993 delete_arrays(arrays);
1996 table& operator=(
const table& x)
2000 static constexpr auto pocca=
2001 alloc_traits::propagate_on_container_copy_assignment::value;
2003 if(
this!=std::addressof(x)){
2007 key_equal tmp_p=x.pred();
2020 if_constexpr<pocca>([&,
this]{
2021 if(al()!=x.al())reserve(0);
2022 copy_assign_if<pocca>(al(),x.al());
2025 noshrink_reserve(x.size());
2026 copy_elements_from(x);
2032#pragma warning(push)
2033#pragma warning(disable:4127
)
2036 table& operator=(table&& x)
2038 alloc_traits::propagate_on_container_move_assignment::value||
2039 alloc_traits::is_always_equal::value)
2043 static constexpr auto pocma=
2044 alloc_traits::propagate_on_container_move_assignment::value;
2046 if(
this!=std::addressof(x)){
2048
2049
2050
2051
2052
2053
2054
2055
2061 swap(pred(),x.pred());
2063 if(pocma||al()==x.al()){
2065 move_assign_if<pocma>(al(),x.al());
2066 swap(size_,x.size_);
2067 swap(arrays,x.arrays);
2072 noshrink_reserve(x.size());
2077
2078
2079 x.for_all_elements([
this](element_type* p){
2080 unchecked_insert(type_policy::move(type_policy::value_from(*p)));
2091 allocator_type get_allocator()
const noexcept{
return al();}
2093 iterator begin()
noexcept
2095 iterator it{arrays.groups,0,arrays.elements};
2096 if(!(arrays.groups[0].match_occupied()&0x1))++it;
2100 const_iterator begin()
const noexcept
2101 {
return const_cast<table*>(
this)->begin();}
2102 iterator end()
noexcept{
return {};}
2103 const_iterator end()
const noexcept{
return const_cast<table*>(
this)->end();}
2104 const_iterator cbegin()
const noexcept{
return begin();}
2105 const_iterator cend()
const noexcept{
return end();}
2107 bool empty()
const noexcept{
return size()==0;}
2108 std::size_t size()
const noexcept{
return size_;}
2109 std::size_t max_size()
const noexcept{
return SIZE_MAX;}
2111 template<
typename... Args>
2114 using emplace_type=
typename std::conditional<
2115 std::is_constructible<init_type,Args...>::value,
2120 using insert_type=
typename std::conditional<
2121 std::is_constructible<
2122 value_type,emplace_type>::value,
2123 emplace_type,element_type
2126 uninitialized_storage<insert_type> s;
2127 auto *p=std::addressof(s.t_);
2129 type_policy::construct(al(),p,std::forward<Args>(args)...);
2131 destroy_on_exit<insert_type> guard{al(),p};
2132 return emplace_impl(type_policy::move(*p));
2135 template<
typename Key,
typename... Args>
2137 Key&& x,Args&&... args)
2139 return emplace_impl(
2140 try_emplace_args_t{},std::forward<Key>(x),std::forward<Args>(args)...);
2144 insert(
const init_type& x){
return emplace_impl(x);}
2147 insert(init_type&& x){
return emplace_impl(std::move(x));}
2151 template<
typename=
void>
2153 insert(
const value_type& x){
return emplace_impl(x);}
2155 template<
typename=
void>
2157 insert(value_type&& x){
return emplace_impl(std::move(x));}
2159 template<
typename T=element_type>
2161 typename std::enable_if<
2162 !std::is_same<T,value_type>::value,
2163 std::pair<iterator,
bool>
2165 insert(element_type&& x){
return emplace_impl(std::move(x));}
2168 bool dependent_value=
false,
2169 typename std::enable_if<
2170 has_mutable_iterator||dependent_value>::type* =
nullptr
2172 void erase(iterator pos)
noexcept{
return erase(const_iterator(pos));}
2175 void erase(const_iterator pos)
noexcept
2177 destroy_element(pos.p);
2178 recover_slot(pos.pc);
2181 template<
typename Key>
2183 auto erase(Key&& x) ->
typename std::enable_if<
2184 !std::is_convertible<Key,iterator>::value&&
2185 !std::is_convertible<Key,const_iterator>::value, std::size_t>::type
2197 alloc_traits::propagate_on_container_swap::value||
2198 alloc_traits::is_always_equal::value)
2202 static constexpr auto pocs=
2203 alloc_traits::propagate_on_container_swap::value;
2206 if_constexpr<pocs>([&,
this]{
2207 swap_if<pocs>(al(),x.al());
2215 swap(pred(),x.pred());
2216 swap(size_,x.size_);
2217 swap(arrays,x.arrays);
2221 void clear()
noexcept
2223 auto p=arrays.elements;
2225 for(
auto pg=arrays.groups,last=pg+arrays.groups_size_mask+1;
2226 pg!=last;++pg,p+=N){
2227 auto mask=pg->match_really_occupied();
2229 destroy_element(p+unchecked_countr_zero(mask));
2235 arrays.groups[arrays.groups_size_mask].set_sentinel();
2237 ml=initial_max_load();
2241 element_type extract(const_iterator pos)
2244 erase_on_exit e{*
this,pos};
2246 return std::move(*pos.p);
2250 template<
typename Hash2,
typename Pred2>
2251 void merge(table<TypePolicy,Hash2,Pred2,Allocator>& x)
2253 x.for_all_elements([&,
this](group_type* pg,
unsigned int n,element_type* p){
2254 erase_on_exit e{x,{pg,n,p}};
2255 if(!emplace_impl(type_policy::move(*p)).second)e.rollback();
2259 template<
typename Hash2,
typename Pred2>
2260 void merge(table<TypePolicy,Hash2,Pred2,Allocator>&& x){merge(x);}
2262 hasher hash_function()
const{
return h();}
2263 key_equal key_eq()
const{
return pred();}
2265 template<
typename Key>
2268 auto hash=hash_for(x);
2269 return find_impl(x,position_for(hash),hash);
2272 template<
typename Key>
2275 return const_cast<table*>(
this)->find(x);
2278 std::size_t capacity()
const noexcept
2280 return arrays.elements?(arrays.groups_size_mask+1)*N-1:0;
2283 float load_factor()
const noexcept
2285 if (capacity() == 0) {
return 0; }
2286 return float(size())/
float(capacity());
2289 float max_load_factor()
const noexcept{
return mlf;}
2291 std::size_t max_load()
const noexcept{
return ml;}
2293 void rehash(std::size_t n)
2295 auto m=size_t(std::ceil(
float(size())/mlf));
2297 if(n)n=capacity_for(n);
2299 if(n!=capacity())unchecked_rehash(n);
2302 void reserve(std::size_t n)
2304 rehash(std::size_t(std::ceil(
float(n)/mlf)));
2307 template<
typename Predicate>
2308 friend std::size_t erase_if(table& x,Predicate pr)
2310 return x.erase_if_impl(pr);
2314 template<
typename,
typename,
typename,
typename>
friend class table;
2315 using arrays_type=table_arrays<element_type,group_type,size_policy>;
2317 struct clear_on_exit
2319 ~clear_on_exit(){x.clear();}
2323 struct erase_on_exit
2325 erase_on_exit(table& x_,const_iterator it_):x{x_},it{it_}{}
2326 ~erase_on_exit(){
if(!rollback_)x.erase(it);}
2328 void rollback(){rollback_=
true;}
2332 bool rollback_=
false;
2336 struct destroy_on_exit
2340 ~destroy_on_exit(){type_policy::destroy(a,p);};
2343 Hash& h(){
return hash_base::get();}
2344 const Hash& h()
const{
return hash_base::get();}
2345 Pred& pred(){
return pred_base::get();}
2346 const Pred& pred()
const{
return pred_base::get();}
2347 Allocator& al(){
return allocator_base::get();}
2348 const Allocator& al()
const{
return allocator_base::get();}
2350 arrays_type new_arrays(std::size_t n)
2352 return arrays_type::new_(al(),n);
2355 void delete_arrays(arrays_type& arrays_)
noexcept
2357 arrays_type::delete_(al(),arrays_);
2360 template<
typename... Args>
2361 void construct_element(element_type* p,Args&&... args)
2363 type_policy::construct(al(),p,std::forward<Args>(args)...);
2366 template<
typename... Args>
2367 void construct_element(element_type* p,try_emplace_args_t,Args&&... args)
2369 construct_element_from_try_emplace_args(
2371 std::integral_constant<
bool,std::is_same<key_type,value_type>::value>{},
2372 std::forward<Args>(args)...);
2375 template<
typename Key,
typename... Args>
2376 void construct_element_from_try_emplace_args(
2377 element_type* p,std::false_type,Key&& x,Args&&... args)
2379 type_policy::construct(
2381 std::piecewise_construct,
2382 std::forward_as_tuple(std::forward<Key>(x)),
2383 std::forward_as_tuple(std::forward<Args>(args)...));
2387
2388
2390 template<
typename Key>
2391 void construct_element_from_try_emplace_args(
2392 element_type* p,std::true_type,Key&& x)
2394 type_policy::construct(al(),p,std::forward<Key>(x));
2397 void destroy_element(element_type* p)
noexcept
2399 type_policy::destroy(al(),p);
2402 struct destroy_element_on_exit
2404 ~destroy_element_on_exit(){this_->destroy_element(p);}
2409 void copy_elements_from(
const table& x)
2413 if(arrays.groups_size_mask==x.arrays.groups_size_mask){
2414 fast_copy_elements_from(x);
2417 x.for_all_elements([
this](
const element_type* p){
2418 unchecked_insert(*p);
2423 void fast_copy_elements_from(
const table& x)
2425 if(arrays.elements){
2426 copy_elements_array_from(x);
2428 arrays.groups,x.arrays.groups,
2429 (arrays.groups_size_mask+1)*
sizeof(group_type));
2434 void copy_elements_array_from(
const table& x)
2436 copy_elements_array_from(
2438 std::integral_constant<
2440 std::is_trivially_copy_constructible<element_type>::value
2442 is_std_allocator<Allocator>::value||
2443 !alloc_has_construct<Allocator,value_type*,
const value_type&>::value)
2448 void copy_elements_array_from(
const table& x,std::true_type )
2451
2452
2454 reinterpret_cast<
unsigned char*>(arrays.elements),
2455 reinterpret_cast<
unsigned char*>(x.arrays.elements),
2456 x.capacity()*
sizeof(value_type));
2459 void copy_elements_array_from(
const table& x,std::false_type )
2461 std::size_t num_constructed=0;
2463 x.for_all_elements([&,
this](
const element_type* p){
2464 construct_element(arrays.elements+(p-x.arrays.elements),*p);
2469 if(num_constructed){
2470 x.for_all_elements_while([&,
this](
const element_type* p){
2471 destroy_element(arrays.elements+(p-x.arrays.elements));
2472 return --num_constructed!=0;
2480 void recover_slot(
unsigned char* pc)
2483
2484
2485
2486 ml-=group_type::maybe_caused_overflow(pc);
2487 group_type::reset(pc);
2491 void recover_slot(group_type* pg,std::size_t pos)
2493 recover_slot(
reinterpret_cast<
unsigned char*>(pg)+pos);
2496 std::size_t initial_max_load()
const
2498 static constexpr std::size_t small_capacity=2*N-1;
2500 auto capacity_=capacity();
2501 if(capacity_<=small_capacity){
2505 return (std::size_t)(mlf*(
float)(capacity_));
2509 template<
typename T>
2510 static inline auto key_from(
const T& x)
2511 ->
decltype(type_policy::extract(x))
2513 return type_policy::extract(x);
2516 template<
typename Key,
typename... Args>
2517 static inline const Key& key_from(
2518 try_emplace_args_t,
const Key& x,
const Args&...)
2523 template<
typename Key>
2524 inline std::size_t hash_for(
const Key& x)
const
2526 return mix_policy::mix(h(),x);
2529 inline std::size_t position_for(std::size_t hash)
const
2531 return position_for(hash,arrays);
2534 static inline std::size_t position_for(
2535 std::size_t hash,
const arrays_type& arrays_)
2537 return size_policy::position(hash,arrays_.groups_size_index);
2540 static inline void prefetch_elements(
const element_type* p)
2543
2544
2545
2546
2547
2551
2552
2553 constexpr int cache_line=64;
2554 const char *p0=
reinterpret_cast<
const char*>(p),
2555 *p1=p0+
sizeof(value_type)*N/2;
2556 for(;p0<p1;p0+=cache_line)prefetch(p0);
2564#pragma warning(push)
2565#pragma warning(disable:4800
)
2568 template<
typename Key>
2570 const Key& x,std::size_t pos0,std::size_t hash)
const
2575 auto pg=arrays.groups+pos;
2576 auto mask=pg->match(hash);
2579 auto p=arrays.elements+pos*N;
2580 prefetch_elements(p);
2582 auto n=unchecked_countr_zero(mask);
2601 template<
typename... Args>
2604 const auto &k=key_from(std::forward<Args>(args)...);
2605 auto hash=hash_for(k);
2606 auto pos0=position_for(hash);
2607 auto it=find_impl(k,pos0,hash);
2614 unchecked_emplace_at(pos0,hash,std::forward<Args>(args)...),
2620 unchecked_emplace_with_rehash(hash,std::forward<Args>(args)...),
2626 static std::size_t capacity_for(std::size_t n)
2628 return size_policy::size(size_index_for<group_type,size_policy>(n))*N-1;
2631 template<
typename... Args>
2633 unchecked_emplace_with_rehash(std::size_t hash,Args&&... args)
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645 auto new_arrays_=new_arrays(std::size_t(
2646 std::ceil(
static_cast<
float>(size_+size_/61+1)/mlf)));
2650 it=nosize_unchecked_emplace_at(
2651 new_arrays_,position_for(hash,new_arrays_),
2652 hash,std::forward<Args>(args)...);
2655 delete_arrays(new_arrays_);
2661 unchecked_rehash(new_arrays_);
2668 auto new_arrays_=new_arrays(n);
2669 unchecked_rehash(new_arrays_);
2674 std::size_t num_destroyed=0;
2676 for_all_elements([&,
this](element_type* p){
2677 nosize_transfer_element(p,new_arrays_,num_destroyed);
2682 for_all_elements_while(
2683 [&,
this](group_type* pg,
unsigned int n,element_type*){
2685 return --num_destroyed!=0;
2689 for_all_elements(new_arrays_,[
this](element_type* p){
2692 delete_arrays(new_arrays_);
2699 if(num_destroyed!=size()){
2700 for_all_elements([
this](element_type* p){
2704 delete_arrays(arrays);
2706 ml=initial_max_load();
2709 void noshrink_reserve(std::size_t n)
2715 n=std::size_t(std::ceil(
float(n)/mlf));
2719 auto new_arrays_=new_arrays(n);
2720 delete_arrays(arrays);
2722 ml=initial_max_load();
2727 template<
typename Value>
2728 void unchecked_insert(Value&& x)
2730 auto hash=hash_for(key_from(x));
2731 unchecked_emplace_at(position_for(hash),hash,std::forward<Value>(x));
2734 void nosize_transfer_element(
2735 element_type* p,
const arrays_type& arrays_,std::size_t& num_destroyed)
2737 nosize_transfer_element(
2738 p,hash_for(key_from(*p)),arrays_,num_destroyed,
2739 std::integral_constant<
2741 std::is_nothrow_move_constructible<init_type>::value||
2742 !std::is_same<element_type,value_type>::value||
2743 !std::is_copy_constructible<element_type>::value>{});
2746 void nosize_transfer_element(
2747 element_type* p,std::size_t hash,
const arrays_type& arrays_,
2748 std::size_t& num_destroyed,std::true_type )
2751
2752
2754 destroy_element_on_exit d{
this,p};
2756 nosize_unchecked_emplace_at(
2757 arrays_,position_for(hash,arrays_),hash,type_policy::move(*p));
2760 void nosize_transfer_element(
2761 element_type* p,std::size_t hash,
const arrays_type& arrays_,
2762 std::size_t& ,std::false_type )
2764 nosize_unchecked_emplace_at(
2765 arrays_,position_for(hash,arrays_),hash,
2766 const_cast<
const element_type&>(*p));
2769 template<
typename... Args>
2770 iterator unchecked_emplace_at(
2771 std::size_t pos0,std::size_t hash,Args&&... args)
2773 auto res=nosize_unchecked_emplace_at(
2774 arrays,pos0,hash,std::forward<Args>(args)...);
2779 template<
typename... Args>
2780 iterator nosize_unchecked_emplace_at(
2781 const arrays_type& arrays_,std::size_t pos0,std::size_t hash,
2784 for(prober pb(pos0);;pb.next(arrays_.groups_size_mask)){
2786 auto pg=arrays_.groups+pos;
2787 auto mask=pg->match_available();
2789 auto n=unchecked_countr_zero(mask);
2790 auto p=arrays_.elements+pos*N+n;
2791 construct_element(p,std::forward<Args>(args)...);
2795 else pg->mark_overflow(hash);
2799 template<
typename Predicate>
2800 std::size_t erase_if_impl(Predicate pr)
2802 std::size_t s=size();
2803 for_all_elements([&,
this](group_type* pg,
unsigned int n,element_type* p){
2804 if(pr(type_policy::value_from(*p))) erase(iterator{pg,n,p});
2806 return std::size_t(s-size());
2809 template<
typename F>
2810 void for_all_elements(F f)
const
2812 for_all_elements(arrays,f);
2815 template<
typename F>
2816 static auto for_all_elements(
const arrays_type& arrays_,F f)
2817 ->
decltype(f(
nullptr),
void())
2819 for_all_elements_while(arrays_,[&](element_type* p){f(p);
return true;});
2822 template<
typename F>
2823 static auto for_all_elements(
const arrays_type& arrays_,F f)
2824 ->
decltype(f(
nullptr,0,
nullptr),
void())
2826 for_all_elements_while(
2827 arrays_,[&](group_type* pg,
unsigned int n,element_type* p)
2828 {f(pg,n,p);
return true;});
2831 template<
typename F>
2832 void for_all_elements_while(F f)
const
2834 for_all_elements_while(arrays,f);
2837 template<
typename F>
2838 static auto for_all_elements_while(
const arrays_type& arrays_,F f)
2839 ->
decltype(f(
nullptr),
void())
2841 for_all_elements_while(
2842 arrays_,[&](group_type*,
unsigned int,element_type* p){
return f(p);});
2845 template<
typename F>
2846 static auto for_all_elements_while(
const arrays_type& arrays_,F f)
2847 ->
decltype(f(
nullptr,0,
nullptr),
void())
2849 auto p=arrays_.elements;
2851 for(
auto pg=arrays_.groups,last=pg+arrays_.groups_size_mask+1;
2852 pg!=last;++pg,p+=N){
2853 auto mask=pg->match_really_occupied();
2855 auto n=unchecked_countr_zero(mask);
2856 if(!f(pg,n,p+n))
return;
2872#pragma GCC diagnostic pop
2880#undef BOOST_UNORDERED_STATIC_ASSERT_HASH_PRED
2881#undef BOOST_UNORDERED_ASSUME
2882#undef BOOST_UNORDERED_HAS_BUILTIN
2889#ifndef BOOST_UNORDERED_DETAIL_TYPE_TRAITS_HPP
2890#define BOOST_UNORDERED_DETAIL_TYPE_TRAITS_HPP
2896#ifndef BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
2897#define BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES 1
2901 namespace unordered {
2907 template <
class,
class =
void>
2908 struct is_transparent :
public std::false_type
2913 struct is_transparent<T,
2914 typename std::void_t<
typename T::is_transparent>>
2915 :
public std::true_type
2919 template <
class,
class Hash,
class KeyEqual>
struct are_transparent
2921 static bool const value =
2922 is_transparent<Hash>::value && is_transparent<KeyEqual>::value;
2925 template <
class Key,
class UnorderedMap>
struct transparent_non_iterable
2927 typedef typename UnorderedMap::hasher hash;
2928 typedef typename UnorderedMap::key_equal key_equal;
2929 typedef typename UnorderedMap::iterator iterator;
2930 typedef typename UnorderedMap::const_iterator const_iterator;
2932 static bool const value =
2933 are_transparent<Key, hash, key_equal>::value &&
2934 !std::is_convertible<Key, iterator>::value &&
2935 !std::is_convertible<Key, const_iterator>::value;
2941 template <
class InputIterator>
2942 constexpr bool const is_input_iterator_v =
2943 !std::is_integral<InputIterator>::value;
2945 template <
class A,
class =
void>
struct is_allocator
2947 constexpr static bool const value =
false;
2951 struct is_allocator<A,
2952 std::void_t<
typename A::value_type,
2953 decltype(std::declval<A&>().allocate(std::size_t{}))> >
2955 constexpr static bool const value =
true;
2959 constexpr bool const is_allocator_v = is_allocator<A>::value;
2962 constexpr bool const is_hash_v =
2963 !std::is_integral<H>::value && !is_allocator_v<H>;
2965 template <
class P>
constexpr bool const is_pred_v = !is_allocator_v<P>;
2976#ifndef BOOST_FUNCTIONAL_HASH_FWD_HPP
2977#define BOOST_FUNCTIONAL_HASH_FWD_HPP
2982namespace container_hash
2985template<
class T>
struct is_range;
2986template<
class T>
struct is_contiguous_range;
2987template<
class T>
struct is_unordered_range;
2988template<
class T>
struct is_tuple_like;
2992template<
class T>
struct hash;
2994template<
class T>
void hash_combine( std::size_t& seed, T
const& v );
2996template<
class It>
void hash_range( std::size_t&, It, It );
2997template<
class It> std::size_t hash_range( It, It );
2999template<
class It>
void hash_unordered_range( std::size_t&, It, It );
3000template<
class It> std::size_t hash_unordered_range( It, It );
3010#ifndef BOOST_UNORDERED_FWD_HPP_INCLUDED
3011#define BOOST_UNORDERED_FWD_HPP_INCLUDED
3016 namespace unordered {
3017 using std::piecewise_construct_t;
3018 using std::piecewise_construct;
3027#ifndef BOOST_UNORDERED_FLAT_SET_FWD_HPP_INCLUDED
3028#define BOOST_UNORDERED_FLAT_SET_FWD_HPP_INCLUDED
3033 namespace unordered {
3034 template <
class Key,
class Hash = boost::hash<Key>,
3035 class KeyEqual = std::equal_to<Key>,
3036 class Allocator = std::allocator<Key> >
3037 class unordered_flat_set;
3039 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
3041 unordered_flat_set<Key, Hash, KeyEqual, Allocator>
const& lhs,
3042 unordered_flat_set<Key, Hash, KeyEqual, Allocator>
const& rhs);
3044 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
3046 unordered_flat_set<Key, Hash, KeyEqual, Allocator>
const& lhs,
3047 unordered_flat_set<Key, Hash, KeyEqual, Allocator>
const& rhs);
3049 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
3050 void swap(unordered_flat_set<Key, Hash, KeyEqual, Allocator>& lhs,
3051 unordered_flat_set<Key, Hash, KeyEqual, Allocator>& rhs)
3052 noexcept(
noexcept(lhs.swap(rhs)));
3055 using boost::unordered::unordered_flat_set;
3057 using boost::unordered::swap;
3058 using boost::unordered::operator==;
3059 using boost::unordered::operator!=;
3067#ifndef BOOST_HASH_IS_RANGE_HPP_INCLUDED
3068#define BOOST_HASH_IS_RANGE_HPP_INCLUDED
3073namespace hash_detail
3076template<
class T,
class It>
3077 std::integral_constant<
bool, !std::is_same<
typename std::remove_cv<T>::type,
typename std::iterator_traits<It>::value_type>::value >
3078 is_range_check( It first, It last );
3080template<
class T>
decltype( is_range_check<T>( std::declval<T
const&>().begin(), std::declval<T
const&>().end() ) ) is_range_(
int );
3081template<
class T> std::false_type is_range_( ... );
3085namespace container_hash
3088template<
class T>
struct is_range:
decltype( hash_detail::is_range_<T>( 0 ) )
3101#ifndef BOOST_HASH_IS_CONTIGUOUS_RANGE_HPP_INCLUDED
3102#define BOOST_HASH_IS_CONTIGUOUS_RANGE_HPP_INCLUDED
3106namespace hash_detail
3109template<
class It,
class T,
class S>
3110 std::integral_constant<
bool, std::is_same<
typename std::iterator_traits<It>::value_type, T>::value && std::is_integral<S>::value >
3111 is_contiguous_range_check( It first, It last, T
const*, T
const*, S );
3113template<
class T>
decltype( is_contiguous_range_check( std::declval<T
const&>().begin(), std::declval<T
const&>().end(), std::declval<T
const&>().data(), std::declval<T
const&>().data() + std::declval<T
const&>().size(), std::declval<T
const&>().size() ) ) is_contiguous_range_(
int );
3114template<
class T> std::false_type is_contiguous_range_( ... );
3116template<
class T>
struct is_contiguous_range:
decltype( hash_detail::is_contiguous_range_<T>( 0 ) )
3122namespace container_hash
3125template<
class T>
struct is_contiguous_range: std::integral_constant<
bool, is_range<T>::value && hash_detail::is_contiguous_range<T>::value >
3137#ifndef BOOST_HASH_IS_UNORDERED_RANGE_HPP_INCLUDED
3138#define BOOST_HASH_IS_UNORDERED_RANGE_HPP_INCLUDED
3142namespace hash_detail
3145template<
class T,
class E = std::true_type>
struct has_hasher_: std::false_type
3149template<
class T>
struct has_hasher_< T, std::integral_constant<
bool,
3150 std::is_same<
typename T::hasher,
typename T::hasher>::value
3157namespace container_hash
3160template<
class T>
struct is_unordered_range: std::integral_constant<
bool, is_range<T>::value && hash_detail::has_hasher_<T>::value >
3168#ifndef BOOST_HASH_IS_TUPLE_LIKE_HPP_INCLUDED
3169#define BOOST_HASH_IS_TUPLE_LIKE_HPP_INCLUDED
3177namespace hash_detail
3180template<
class T,
class E = std::true_type>
struct is_tuple_like_: std::false_type
3184template<
class T>
struct is_tuple_like_<T, std::integral_constant<
bool, std::tuple_size<T>::value == std::tuple_size<T>::value> >: std::true_type
3190namespace container_hash
3193template<
class T>
struct is_tuple_like: hash_detail::is_tuple_like_<T>
3206#ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
3207#define BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
3211namespace hash_detail
3214template <std::size_t I,
typename T>
3216typename std::enable_if<(I == std::tuple_size<T>::value),
void>::type
3217 hash_combine_tuple_like( std::size_t&, T
const& )
3221template <std::size_t I,
typename T>
3223typename std::enable_if<(I < std::tuple_size<T>::value),
void>::type
3224 hash_combine_tuple_like( std::size_t& seed, T
const& v )
3227 boost::hash_combine( seed, get<I>( v ) );
3229 boost::hash_detail::hash_combine_tuple_like<I + 1>( seed, v );
3232template <
typename T>
3233inline std::size_t hash_tuple_like( T
const& v )
3235 std::size_t seed = 0;
3237 boost::hash_detail::hash_combine_tuple_like<0>( seed, v );
3246typename std::enable_if<
3247 container_hash::is_tuple_like<T>::value && !container_hash::is_range<T>::value,
3249 hash_value( T
const& v )
3251 return boost::hash_detail::hash_tuple_like( v );
3261#ifndef BOOST_HASH_DETAIL_HASH_MIX_HPP
3262#define BOOST_HASH_DETAIL_HASH_MIX_HPP
3266namespace hash_detail
3269template<std::size_t Bits>
struct hash_mix_impl;
3319template<>
struct hash_mix_impl<64>
3321 inline static std::uint64_t fn( std::uint64_t x )
3323 std::uint64_t
const m = (std::uint64_t(0xe9846af) << 32) + 0x9b1a615d;
3340template<>
struct hash_mix_impl<32>
3342 inline static std::uint32_t fn( std::uint32_t x )
3344 std::uint32_t
const m1 = 0x21f0aaad;
3345 std::uint32_t
const m2 = 0x735a2d97;
3357inline std::size_t hash_mix( std::size_t v )
3359 return hash_mix_impl<
sizeof(std::size_t) * CHAR_BIT>::fn( v );
3370#ifndef BOOST_HASH_DETAIL_MULX_HPP
3371#define BOOST_HASH_DETAIL_MULX_HPP
3379namespace hash_detail
3382#if defined(_MSC_VER) && defined(_M_X64) && !defined(__clang__
)
3384__forceinline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
3387 std::uint64_t r = _umul128( x, y, &r2 );
3391#elif defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__
)
3393__forceinline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
3395 std::uint64_t r = x * y;
3396 std::uint64_t r2 = __umulh( x, y );
3400#elif defined(__SIZEOF_INT128__
)
3402inline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
3404 __uint128_t r =
static_cast<__uint128_t>( x ) * y;
3405 return static_cast<std::uint64_t>( r ) ^
static_cast<std::uint64_t>( r >> 64 );
3410inline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
3412 std::uint64_t x1 =
static_cast<std::uint32_t>( x );
3413 std::uint64_t x2 = x >> 32;
3415 std::uint64_t y1 =
static_cast<std::uint32_t>( y );
3416 std::uint64_t y2 = y >> 32;
3418 std::uint64_t r3 = x2 * y2;
3420 std::uint64_t r2a = x1 * y2;
3424 std::uint64_t r2b = x2 * y1;
3428 std::uint64_t r1 = x1 * y1;
3430 std::uint64_t r2 = (r1 >> 32) +
static_cast<std::uint32_t>( r2a ) +
static_cast<std::uint32_t>( r2b );
3432 r1 = (r2 << 32) +
static_cast<std::uint32_t>( r1 );
3448#ifndef BOOST_HASH_DETAIL_HASH_RANGE_HPP
3449#define BOOST_HASH_DETAIL_HASH_RANGE_HPP
3453namespace hash_detail
3456template<
class T>
struct is_char_type:
public std::false_type {};
3460template<>
struct is_char_type<
char>:
public std::true_type {};
3461template<>
struct is_char_type<
signed char>:
public std::true_type {};
3462template<>
struct is_char_type<
unsigned char>:
public std::true_type {};
3464#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
3465template<>
struct is_char_type<char8_t>:
public std::true_type {};
3468#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3469template<>
struct is_char_type<std::byte>:
public std::true_type {};
3477inline typename std::enable_if<
3478 !is_char_type<
typename std::iterator_traits<It>::value_type>::value,
3480 hash_range( std::size_t seed, It first, It last )
3482 for( ; first != last; ++first )
3484 hash_combine<
typename std::iterator_traits<It>::value_type>( seed, *first );
3492template<
class It>
inline std::uint32_t read32le( It p )
3498 static_cast<std::uint32_t>(
static_cast<
unsigned char>( p[0] ) ) |
3499 static_cast<std::uint32_t>(
static_cast<
unsigned char>( p[1] ) ) << 8 |
3500 static_cast<std::uint32_t>(
static_cast<
unsigned char>( p[2] ) ) << 16 |
3501 static_cast<std::uint32_t>(
static_cast<
unsigned char>( p[3] ) ) << 24;
3506#if defined(_MSC_VER) && !defined(__clang__
)
3508template<
class T>
inline std::uint32_t read32le( T* p )
3512 std::memcpy( &w, p, 4 );
3518inline std::uint64_t mul32( std::uint32_t x, std::uint32_t y )
3520 return static_cast<std::uint64_t>( x ) * y;
3524inline typename std::enable_if<
3525 is_char_type<
typename std::iterator_traits<It>::value_type>::value &&
3526 std::is_same<
typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value &&
3527 std::numeric_limits<std::size_t>::digits <= 32,
3529 hash_range( std::size_t seed, It first, It last )
3532 std::size_t n =
static_cast<std::size_t>( last - first );
3534 std::uint32_t
const q = 0x9e3779b9U;
3535 std::uint32_t
const k = 0xe35e67b1U;
3537 std::uint64_t h = mul32(
static_cast<std::uint32_t>( seed ) + q, k );
3538 std::uint32_t w =
static_cast<std::uint32_t>( h & 0xFFFFFFFF );
3544 std::uint32_t v1 = read32le( p );
3547 h ^= mul32( v1 + w, k );
3554 std::uint32_t v1 = 0;
3558 std::size_t
const x1 = ( n - 1 ) & 2;
3559 std::size_t
const x2 = n >> 1;
3562 static_cast<std::uint32_t>(
static_cast<
unsigned char>( p[
static_cast<std::ptrdiff_t>( x1 ) ] ) ) << x1 * 8 |
3563 static_cast<std::uint32_t>(
static_cast<
unsigned char>( p[
static_cast<std::ptrdiff_t>( x2 ) ] ) ) << x2 * 8 |
3564 static_cast<std::uint32_t>(
static_cast<
unsigned char>( p[ 0 ] ) );
3568 h ^= mul32( v1 + w, k );
3572 h ^= mul32(
static_cast<std::uint32_t>( h & 0xFFFFFFFF ) + w,
static_cast<std::uint32_t>( h >> 32 ) + w + k );
3574 return static_cast<std::uint32_t>( h & 0xFFFFFFFF ) ^
static_cast<std::uint32_t>( h >> 32 );
3578inline typename std::enable_if<
3579 is_char_type<
typename std::iterator_traits<It>::value_type>::value &&
3580 !std::is_same<
typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value &&
3581 std::numeric_limits<std::size_t>::digits <= 32,
3583 hash_range( std::size_t seed, It first, It last )
3587 std::uint32_t
const q = 0x9e3779b9U;
3588 std::uint32_t
const k = 0xe35e67b1U;
3590 std::uint64_t h = mul32(
static_cast<std::uint32_t>( seed ) + q, k );
3591 std::uint32_t w =
static_cast<std::uint32_t>( h & 0xFFFFFFFF );
3593 std::uint32_t v1 = 0;
3604 v1 |=
static_cast<std::uint32_t>(
static_cast<
unsigned char>( *first ) );
3613 v1 |=
static_cast<std::uint32_t>(
static_cast<
unsigned char>( *first ) ) << 8;
3622 v1 |=
static_cast<std::uint32_t>(
static_cast<
unsigned char>( *first ) ) << 16;
3631 v1 |=
static_cast<std::uint32_t>(
static_cast<
unsigned char>( *first ) ) << 24;
3636 h ^= mul32( v1 + w, k );
3642 h ^= mul32( v1 + w, k );
3645 h ^= mul32(
static_cast<std::uint32_t>( h & 0xFFFFFFFF ) + w,
static_cast<std::uint32_t>( h >> 32 ) + w + k );
3647 return static_cast<std::uint32_t>( h & 0xFFFFFFFF ) ^
static_cast<std::uint32_t>( h >> 32 );
3652template<
class It>
inline std::uint64_t read64le( It p )
3655 static_cast<std::uint64_t>(
static_cast<
unsigned char>( p[0] ) ) |
3656 static_cast<std::uint64_t>(
static_cast<
unsigned char>( p[1] ) ) << 8 |
3657 static_cast<std::uint64_t>(
static_cast<
unsigned char>( p[2] ) ) << 16 |
3658 static_cast<std::uint64_t>(
static_cast<
unsigned char>( p[3] ) ) << 24 |
3659 static_cast<std::uint64_t>(
static_cast<
unsigned char>( p[4] ) ) << 32 |
3660 static_cast<std::uint64_t>(
static_cast<
unsigned char>( p[5] ) ) << 40 |
3661 static_cast<std::uint64_t>(
static_cast<
unsigned char>( p[6] ) ) << 48 |
3662 static_cast<std::uint64_t>(
static_cast<
unsigned char>( p[7] ) ) << 56;
3667#if defined(_MSC_VER) && !defined(__clang__
)
3669template<
class T>
inline std::uint64_t read64le( T* p )
3673 std::memcpy( &w, p, 8 );
3680inline typename std::enable_if<
3681 is_char_type<
typename std::iterator_traits<It>::value_type>::value &&
3682 std::is_same<
typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value &&
3683 (std::numeric_limits<std::size_t>::digits > 32),
3685 hash_range( std::size_t seed, It first, It last )
3688 std::size_t n =
static_cast<std::size_t>( last - first );
3690 std::uint64_t
const q =
static_cast<std::uint64_t>( 0x9e3779b9 ) << 32 | 0x7f4a7c15;
3691 std::uint64_t
const k =
static_cast<std::uint64_t>( 0xdf442d22 ) << 32 | 0xce4859b9;
3693 std::uint64_t w = mulx( seed + q, k );
3694 std::uint64_t h = w ^ n;
3698 std::uint64_t v1 = read64le( p );
3701 h ^= mulx( v1 + w, k );
3708 std::uint64_t v1 = 0;
3712 v1 =
static_cast<std::uint64_t>( read32le( p +
static_cast<std::ptrdiff_t>( n - 4 ) ) ) << ( n - 4 ) * 8 | read32le( p );
3716 std::size_t
const x1 = ( n - 1 ) & 2;
3717 std::size_t
const x2 = n >> 1;
3720 static_cast<std::uint64_t>(
static_cast<
unsigned char>( p[
static_cast<std::ptrdiff_t>( x1 ) ] ) ) << x1 * 8 |
3721 static_cast<std::uint64_t>(
static_cast<
unsigned char>( p[
static_cast<std::ptrdiff_t>( x2 ) ] ) ) << x2 * 8 |
3722 static_cast<std::uint64_t>(
static_cast<
unsigned char>( p[ 0 ] ) );
3726 h ^= mulx( v1 + w, k );
3729 return mulx( h + w, k );
3733inline typename std::enable_if<
3734 is_char_type<
typename std::iterator_traits<It>::value_type>::value &&
3735 !std::is_same<
typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value &&
3736 (std::numeric_limits<std::size_t>::digits > 32),
3738 hash_range( std::size_t seed, It first, It last )
3742 std::uint64_t
const q =
static_cast<std::uint64_t>( 0x9e3779b9 ) << 32 | 0x7f4a7c15;
3743 std::uint64_t
const k =
static_cast<std::uint64_t>( 0xdf442d22 ) << 32 | 0xce4859b9;
3745 std::uint64_t w = mulx( seed + q, k );
3746 std::uint64_t h = w;
3748 std::uint64_t v1 = 0;
3759 v1 |=
static_cast<std::uint64_t>(
static_cast<
unsigned char>( *first ) );
3768 v1 |=
static_cast<std::uint64_t>(
static_cast<
unsigned char>( *first ) ) << 8;
3777 v1 |=
static_cast<std::uint64_t>(
static_cast<
unsigned char>( *first ) ) << 16;
3786 v1 |=
static_cast<std::uint64_t>(
static_cast<
unsigned char>( *first ) ) << 24;
3795 v1 |=
static_cast<std::uint64_t>(
static_cast<
unsigned char>( *first ) ) << 32;
3804 v1 |=
static_cast<std::uint64_t>(
static_cast<
unsigned char>( *first ) ) << 40;
3813 v1 |=
static_cast<std::uint64_t>(
static_cast<
unsigned char>( *first ) ) << 48;
3822 v1 |=
static_cast<std::uint64_t>(
static_cast<
unsigned char>( *first ) ) << 56;
3827 h ^= mulx( v1 + w, k );
3833 h ^= mulx( v1 + w, k );
3835 return mulx( h + w, k );
3851#ifndef BOOST_FUNCTIONAL_HASH_HASH_HPP
3852#define BOOST_FUNCTIONAL_HASH_HASH_HPP
3856# include <string_view>
3867 namespace hash_detail
3870 bool bigger_than_size_t = (
sizeof(T) >
sizeof(std::size_t)),
3871 bool is_unsigned = std::is_unsigned<T>::value,
3872 std::size_t size_t_bits =
sizeof(std::size_t) * CHAR_BIT,
3873 std::size_t type_bits =
sizeof(T) * CHAR_BIT>
3874 struct hash_integral_impl;
3876 template<
class T,
bool is_unsigned, std::size_t size_t_bits, std::size_t type_bits>
struct hash_integral_impl<T,
false, is_unsigned, size_t_bits, type_bits>
3878 static std::size_t fn( T v )
3880 return static_cast<std::size_t>( v );
3884 template<
class T, std::size_t size_t_bits, std::size_t type_bits>
struct hash_integral_impl<T,
true,
false, size_t_bits, type_bits>
3886 static std::size_t fn( T v )
3888 typedef typename std::make_unsigned<T>::type U;
3892 return hash_integral_impl<U>::fn(
static_cast<U>( v ) );
3896 return ~hash_integral_impl<U>::fn(
static_cast<U>( ~
static_cast<U>( v ) ) );
3901 template<
class T>
struct hash_integral_impl<T,
true,
true, 32, 64>
3903 static std::size_t fn( T v )
3905 std::size_t seed = 0;
3907 seed =
static_cast<std::size_t>( v >> 32 ) + hash_detail::hash_mix( seed );
3908 seed =
static_cast<std::size_t>( v & 0xFFFFFFFF ) + hash_detail::hash_mix( seed );
3914 template<
class T>
struct hash_integral_impl<T,
true,
true, 32, 128>
3916 static std::size_t fn( T v )
3918 std::size_t seed = 0;
3920 seed =
static_cast<std::size_t>( v >> 96 ) + hash_detail::hash_mix( seed );
3921 seed =
static_cast<std::size_t>( v >> 64 ) + hash_detail::hash_mix( seed );
3922 seed =
static_cast<std::size_t>( v >> 32 ) + hash_detail::hash_mix( seed );
3923 seed =
static_cast<std::size_t>( v ) + hash_detail::hash_mix( seed );
3929 template<
class T>
struct hash_integral_impl<T,
true,
true, 64, 128>
3931 static std::size_t fn( T v )
3933 std::size_t seed = 0;
3935 seed =
static_cast<std::size_t>( v >> 64 ) + hash_detail::hash_mix( seed );
3936 seed =
static_cast<std::size_t>( v ) + hash_detail::hash_mix( seed );
3944 template <
typename T>
3945 typename std::enable_if<std::is_integral<T>::value, std::size_t>::type
3948 return hash_detail::hash_integral_impl<T>::fn( v );
3953 template <
typename T>
3954 typename std::enable_if<std::is_enum<T>::value, std::size_t>::type
3971 return static_cast<std::size_t>( v );
3976 namespace hash_detail
3979 std::size_t Bits =
sizeof(T) * CHAR_BIT,
3980 int Digits = std::numeric_limits<T>::digits>
3981 struct hash_float_impl;
3984 template<
class T,
int Digits>
struct hash_float_impl<T, 32, Digits>
3986 static std::size_t fn( T v )
3989 std::memcpy( &w, &v,
sizeof( v ) );
3996 template<
class T,
int Digits>
struct hash_float_impl<T, 64, Digits>
3998 static std::size_t fn( T v )
4001 std::memcpy( &w, &v,
sizeof( v ) );
4003 return hash_value( w );
4008 template<
class T>
struct hash_float_impl<T, 96, 64>
4010 static std::size_t fn( T v )
4012 std::uint64_t w[ 2 ] = {};
4013 std::memcpy( &w, &v, 80 / CHAR_BIT );
4015 std::size_t seed = 0;
4017 seed = hash_value( w[0] ) + hash_detail::hash_mix( seed );
4018 seed = hash_value( w[1] ) + hash_detail::hash_mix( seed );
4025 template<
class T>
struct hash_float_impl<T, 128, 64>
4027 static std::size_t fn( T v )
4029 std::uint64_t w[ 2 ] = {};
4030 std::memcpy( &w, &v, 80 / CHAR_BIT );
4032 std::size_t seed = 0;
4034 seed = hash_value( w[0] ) + hash_detail::hash_mix( seed );
4035 seed = hash_value( w[1] ) + hash_detail::hash_mix( seed );
4042 template<
class T,
int Digits>
struct hash_float_impl<T, 128, Digits>
4044 static std::size_t fn( T v )
4046 std::uint64_t w[ 2 ];
4047 std::memcpy( &w, &v,
sizeof( v ) );
4049 std::size_t seed = 0;
4051#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__
) && __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__
4053 seed = hash_value( w[1] ) + hash_detail::hash_mix( seed );
4054 seed = hash_value( w[0] ) + hash_detail::hash_mix( seed );
4058 seed = hash_value( w[0] ) + hash_detail::hash_mix( seed );
4059 seed = hash_value( w[1] ) + hash_detail::hash_mix( seed );
4068 template <
typename T>
4069 typename std::enable_if<std::is_floating_point<T>::value, std::size_t>::type
4072 return boost::hash_detail::hash_float_impl<T>::fn( v + 0 );
4078 template <
class T> std::size_t hash_value( T*
const& v )
4080 std::uintptr_t x =
reinterpret_cast<std::uintptr_t>( v );
4081 return boost::hash_value( x + (x >> 3) );
4086 template<
class T, std::size_t N>
4087 inline std::size_t hash_value( T
const (&x)[ N ] )
4089 return boost::hash_range( x, x + N );
4092 template<
class T, std::size_t N>
4093 inline std::size_t hash_value( T (&x)[ N ] )
4095 return boost::hash_range( x, x + N );
4101 std::size_t hash_value( std::complex<T>
const& v )
4103 std::size_t re = boost::hash<T>()( v.real() );
4104 std::size_t im = boost::hash<T>()( v.imag() );
4106 return re + hash_detail::hash_mix( im );
4111 template <
class A,
class B>
4112 std::size_t hash_value( std::pair<A, B>
const& v )
4114 std::size_t seed = 0;
4116 boost::hash_combine( seed, v.first );
4117 boost::hash_combine( seed, v.second );
4124 template <
typename T>
4125 typename std::enable_if<container_hash::is_range<T>::value && !container_hash::is_contiguous_range<T>::value && !container_hash::is_unordered_range<T>::value, std::size_t>::type
4126 hash_value( T
const& v )
4128 return boost::hash_range( v.begin(), v.end() );
4133 template <
typename T>
4134 typename std::enable_if<container_hash::is_contiguous_range<T>::value, std::size_t>::type
4135 hash_value( T
const& v )
4137 return boost::hash_range( v.data(), v.data() + v.size() );
4142 template <
typename T>
4143 typename std::enable_if<container_hash::is_unordered_range<T>::value, std::size_t>::type
4144 hash_value( T
const& v )
4146 return boost::hash_unordered_range( v.begin(), v.end() );
4149#if ( ( defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION < 142
) || ( !defined(_MSVC_STL_VERSION) && defined(_CPPLIB_VER) && _CPPLIB_VER >= 520
) )
4153 template<
template<
class...>
class L,
class... T>
4154 typename std::enable_if<container_hash::is_range<L<T...>>::value && !container_hash::is_contiguous_range<L<T...>>::value && !container_hash::is_unordered_range<L<T...>>::value, std::size_t>::type
4155 hash_value( L<T...>
const& v )
4157 return boost::hash_range( v.begin(), v.end() );
4162 template<
template<
class...>
class L,
class... T>
4163 typename std::enable_if<container_hash::is_contiguous_range<L<T...>>::value, std::size_t>::type
4164 hash_value( L<T...>
const& v )
4166 return boost::hash_range( v.data(), v.data() + v.size() );
4169 template<
template<
class, std::size_t>
class L,
class T, std::size_t N>
4170 typename std::enable_if<container_hash::is_contiguous_range<L<T, N>>::value, std::size_t>::type
4171 hash_value( L<T, N>
const& v )
4173 return boost::hash_range( v.data(), v.data() + v.size() );
4178 template<
template<
class...>
class L,
class... T>
4179 typename std::enable_if<container_hash::is_unordered_range<L<T...>>::value, std::size_t>::type
4180 hash_value( L<T...>
const& v )
4182 return boost::hash_unordered_range( v.begin(), v.end() );
4189 template <
typename T>
4190 std::size_t hash_value( std::shared_ptr<T>
const& x )
4192 return boost::hash_value( x.get() );
4195 template <
typename T,
typename Deleter>
4196 std::size_t hash_value( std::unique_ptr<T, Deleter>
const& x )
4198 return boost::hash_value( x.get() );
4203 inline std::size_t hash_value( std::type_index
const& v )
4205 return v.hash_code();
4210 inline std::size_t hash_value( std::error_code
const& v )
4212 std::size_t seed = 0;
4214 boost::hash_combine( seed, v.value() );
4215 boost::hash_combine( seed, &v.category() );
4220 inline std::size_t hash_value( std::error_condition
const& v )
4222 std::size_t seed = 0;
4224 boost::hash_combine( seed, v.value() );
4225 boost::hash_combine( seed, &v.category() );
4232 template <
typename T>
4233 typename std::enable_if<std::is_same<T, std::nullptr_t>::value, std::size_t>::type
4234 hash_value( T
const& )
4236 return boost::hash_value(
static_cast<
void*>(
nullptr ) );
4241 template <
typename T>
4242 std::size_t hash_value( std::optional<T>
const& v )
4251 return boost::hash<T>()(*v);
4257 inline std::size_t hash_value( std::monostate )
4262 template <
typename... Types>
4263 std::size_t hash_value( std::variant<Types...>
const& v )
4265 std::size_t seed = 0;
4267 hash_combine( seed, v.index() );
4268 std::visit( [&seed](
auto&& x) { hash_combine(seed, x); }, v );
4278 inline void hash_combine( std::size_t& seed, T
const& v )
4280 seed = boost::hash_detail::hash_mix( seed + 0x9e3779b9 + boost::hash<T>()( v ) );
4288 inline void hash_range( std::size_t& seed, It first, It last )
4290 seed = hash_detail::hash_range( seed, first, last );
4294 inline std::size_t hash_range( It first, It last )
4296 std::size_t seed = 0;
4298 hash_range( seed, first, last );
4308 inline void hash_unordered_range( std::size_t& seed, It first, It last )
4311 std::size_t
const s2( seed );
4313 for( ; first != last; ++first )
4315 std::size_t s3( s2 );
4317 hash_combine<
typename std::iterator_traits<It>::value_type>( s3, *first );
4326 inline std::size_t hash_unordered_range( It first, It last )
4328 std::size_t seed = 0;
4330 hash_unordered_range( seed, first, last );
4339 template <
class T>
struct hash
4341 typedef T argument_type;
4342 typedef std::size_t result_type;
4344 std::size_t operator()( T
const& val )
const
4346 return hash_value( val );
4350#if ( ( defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION < 142
) || ( !defined(_MSVC_STL_VERSION) && defined(_CPPLIB_VER) && _CPPLIB_VER >= 520
) )
4354 template<
class E,
class T,
class A>
struct hash< std::basic_string<E, T, A> >
4356 typedef std::basic_string<E, T, A> argument_type;
4357 typedef std::size_t result_type;
4359 std::size_t operator()( std::basic_string<E, T, A>
const& val )
const
4361 return boost::hash_value( val );
4371 template<
class T>
struct hash_is_avalanching;
4372 template<
class Ch>
struct hash_is_avalanching< boost::hash< std::basic_string<Ch> > >: std::is_integral<Ch> {};
4374#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
4375 template<>
struct hash_is_avalanching< boost::hash< std::basic_string<char8_t> > >: std::true_type {};
4378 template<
class Ch>
struct hash_is_avalanching< boost::hash< std::basic_string_view<Ch> > >: std::is_integral<Ch> {};
4380#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
4381 template<>
struct hash_is_avalanching< boost::hash< std::basic_string_view<char8_t> > >: std::true_type {};
4393#ifndef BOOST_UNORDERED_UNORDERED_FLAT_SET_HPP_INCLUDED
4394#define BOOST_UNORDERED_UNORDERED_FLAT_SET_HPP_INCLUDED
4399 namespace unordered {
4402#pragma warning(push)
4403#pragma warning(disable : 4714
)
4407 template <
class Key>
struct flat_set_types
4409 using key_type = Key;
4410 using init_type = Key;
4411 using value_type = Key;
4413 static Key
const& extract(value_type
const& key) {
return key; }
4415 using element_type = value_type;
4417 static Key& value_from(element_type& x) {
return x; }
4419 static element_type&& move(element_type& x) {
return std::move(x); }
4421 template <
class A,
class... Args>
4422 static void construct(A& al, value_type* p, Args&&... args)
4424 std::allocator_traits<A>::construct(al, p, std::forward<Args>(args)...);
4427 template <
class A>
static void destroy(A& al, value_type* p)
noexcept
4429 std::allocator_traits<A>::destroy(al, p);
4434 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
4435 class unordered_flat_set
4437 using set_types = detail::flat_set_types<Key>;
4439 using table_type = detail::foa::table<set_types, Hash, KeyEqual,
4440 typename std::allocator_traits<Allocator>::
template rebind_alloc<
4441 typename set_types::value_type>>;
4445 template <
class K,
class H,
class KE,
class A,
class Pred>
4446 typename unordered_flat_set<K, H, KE, A>::size_type
friend erase_if(
4447 unordered_flat_set<K, H, KE, A>& set, Pred pred);
4450 using key_type = Key;
4451 using value_type =
typename set_types::value_type;
4452 using init_type =
typename set_types::init_type;
4453 using size_type = std::size_t;
4454 using difference_type = std::ptrdiff_t;
4455 using hasher = Hash;
4456 using key_equal = KeyEqual;
4457 using allocator_type = Allocator;
4458 using reference = value_type&;
4459 using const_reference = value_type
const&;
4460 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
4461 using const_pointer =
4462 typename std::allocator_traits<allocator_type>::const_pointer;
4463 using iterator =
typename table_type::iterator;
4464 using const_iterator =
typename table_type::const_iterator;
4466 unordered_flat_set() : unordered_flat_set(0) {}
4468 explicit unordered_flat_set(size_type n, hasher
const& h = hasher(),
4469 key_equal
const& pred = key_equal(),
4470 allocator_type
const& a = allocator_type())
4471 : table_(n, h, pred, a)
4475 unordered_flat_set(size_type n, allocator_type
const& a)
4476 : unordered_flat_set(n, hasher(), key_equal(), a)
4480 unordered_flat_set(size_type n, hasher
const& h, allocator_type
const& a)
4481 : unordered_flat_set(n, h, key_equal(), a)
4485 template <
class InputIterator>
4487 InputIterator f, InputIterator l, allocator_type
const& a)
4488 : unordered_flat_set(f, l, size_type(0), hasher(), key_equal(), a)
4492 explicit unordered_flat_set(allocator_type
const& a)
4493 : unordered_flat_set(0, a)
4497 template <
class Iterator>
4498 unordered_flat_set(Iterator first, Iterator last, size_type n = 0,
4499 hasher
const& h = hasher(), key_equal
const& pred = key_equal(),
4500 allocator_type
const& a = allocator_type())
4501 : unordered_flat_set(n, h, pred, a)
4503 this->insert(first, last);
4506 template <
class InputIt>
4508 InputIt first, InputIt last, size_type n, allocator_type
const& a)
4509 : unordered_flat_set(first, last, n, hasher(), key_equal(), a)
4513 template <
class Iterator>
4514 unordered_flat_set(Iterator first, Iterator last, size_type n,
4515 hasher
const& h, allocator_type
const& a)
4516 : unordered_flat_set(first, last, n, h, key_equal(), a)
4520 unordered_flat_set(unordered_flat_set
const& other) : table_(other.table_)
4525 unordered_flat_set
const& other, allocator_type
const& a)
4526 : table_(other.table_, a)
4530 unordered_flat_set(unordered_flat_set&& other)
4531 noexcept(std::is_nothrow_move_constructible<hasher>::value&&
4532 std::is_nothrow_move_constructible<key_equal>::value&&
4533 std::is_nothrow_move_constructible<allocator_type>::value)
4534 : table_(std::move(other.table_))
4538 unordered_flat_set(unordered_flat_set&& other, allocator_type
const& al)
4539 : table_(std::move(other.table_), al)
4543 unordered_flat_set(std::initializer_list<value_type> ilist,
4544 size_type n = 0, hasher
const& h = hasher(),
4545 key_equal
const& pred = key_equal(),
4546 allocator_type
const& a = allocator_type())
4547 : unordered_flat_set(ilist.begin(), ilist.end(), n, h, pred, a)
4552 std::initializer_list<value_type> il, allocator_type
const& a)
4553 : unordered_flat_set(il, size_type(0), hasher(), key_equal(), a)
4557 unordered_flat_set(std::initializer_list<value_type> init, size_type n,
4558 allocator_type
const& a)
4559 : unordered_flat_set(init, n, hasher(), key_equal(), a)
4563 unordered_flat_set(std::initializer_list<value_type> init, size_type n,
4564 hasher
const& h, allocator_type
const& a)
4565 : unordered_flat_set(init, n, h, key_equal(), a)
4569 ~unordered_flat_set() =
default;
4571 unordered_flat_set& operator=(unordered_flat_set
const& other)
4573 table_ = other.table_;
4577 unordered_flat_set& operator=(unordered_flat_set&& other)
noexcept(
4578 noexcept(std::declval<table_type&>() = std::declval<table_type&&>()))
4580 table_ = std::move(other.table_);
4584 allocator_type get_allocator()
const noexcept
4586 return table_.get_allocator();
4592 iterator begin()
noexcept {
return table_.begin(); }
4593 const_iterator begin()
const noexcept {
return table_.begin(); }
4594 const_iterator cbegin()
const noexcept {
return table_.cbegin(); }
4596 iterator end()
noexcept {
return table_.end(); }
4597 const_iterator end()
const noexcept {
return table_.end(); }
4598 const_iterator cend()
const noexcept {
return table_.cend(); }
4603 [[nodiscard]]
bool empty()
const noexcept
4605 return table_.empty();
4608 size_type size()
const noexcept {
return table_.size(); }
4610 size_type max_size()
const noexcept {
return table_.max_size(); }
4615 void clear()
noexcept { table_.clear(); }
4618 value_type
const& value)
4620 return table_.insert(value);
4625 return table_.insert(std::move(value));
4630 detail::transparent_non_iterable<K, unordered_flat_set>::value,
4631 std::pair<iterator,
bool> >::type
4634 return table_.try_emplace(std::forward<K>(k));
4639 return table_.insert(value).first;
4644 return table_.insert(std::move(value)).first;
4649 detail::transparent_non_iterable<K, unordered_flat_set>::value,
4651 insert(const_iterator, K&& k)
4653 return table_.try_emplace(std::forward<K>(k)).first;
4656 template <
class InputIterator>
4657 void insert(InputIterator first, InputIterator last)
4659 for (
auto pos = first; pos != last; ++pos) {
4660 table_.emplace(*pos);
4664 void insert(std::initializer_list<value_type> ilist)
4666 this->insert(ilist.begin(), ilist.end());
4669 template <
class... Args>
4672 return table_.emplace(std::forward<Args>(args)...);
4675 template <
class... Args>
4678 return table_.emplace(std::forward<Args>(args)...).first;
4683 return table_.erase(pos);
4685 iterator erase(const_iterator first, const_iterator last)
4687 while (first != last) {
4688 this->erase(first++);
4690 return iterator{detail::foa::const_iterator_cast_tag{}, last};
4695 return table_.erase(key);
4700 detail::transparent_non_iterable<K, unordered_flat_set>::value,
4704 return table_.erase(key);
4707 void swap(unordered_flat_set& rhs)
noexcept(
4708 noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
4710 table_.swap(rhs.table_);
4713 template <
class H2,
class P2>
4714 void merge(unordered_flat_set<key_type, H2, P2, allocator_type>& source)
4716 table_.merge(source.table_);
4719 template <
class H2,
class P2>
4720 void merge(unordered_flat_set<key_type, H2, P2, allocator_type>&& source)
4722 table_.merge(std::move(source.table_));
4730 auto pos = table_.find(key);
4731 return pos != table_.end() ? 1 : 0;
4736 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
4737 count(K
const& key)
const
4739 auto pos = table_.find(key);
4740 return pos != table_.end() ? 1 : 0;
4745 return table_.find(key);
4750 return table_.find(key);
4755 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
4759 return table_.find(key);
4764 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
4765 const_iterator>::type
4766 find(K
const& key)
const
4768 return table_.find(key);
4773 return this->find(key) !=
this->end();
4778 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
4780 contains(K
const& key)
const
4782 return this->find(key) !=
this->end();
4785 std::pair<iterator, iterator> equal_range(key_type
const& key)
4787 auto pos = table_.find(key);
4788 if (pos == table_.end()) {
4797 std::pair<const_iterator, const_iterator> equal_range(
4798 key_type
const& key)
const
4800 auto pos = table_.find(key);
4801 if (pos == table_.end()) {
4811 typename std::enable_if<
4812 detail::are_transparent<K, hasher, key_equal>::value,
4813 std::pair<iterator, iterator> >::type
4814 equal_range(K
const& key)
4816 auto pos = table_.find(key);
4817 if (pos == table_.end()) {
4827 typename std::enable_if<
4828 detail::are_transparent<K, hasher, key_equal>::value,
4829 std::pair<const_iterator, const_iterator> >::type
4830 equal_range(K
const& key)
const
4832 auto pos = table_.find(key);
4833 if (pos == table_.end()) {
4845 size_type bucket_count()
const noexcept {
return table_.capacity(); }
4847 float load_factor()
const noexcept {
return table_.load_factor(); }
4849 float max_load_factor()
const noexcept
4851 return table_.max_load_factor();
4854 void max_load_factor(
float) {}
4856 size_type max_load()
const noexcept {
return table_.max_load(); }
4858 void rehash(size_type n) { table_.rehash(n); }
4860 void reserve(size_type n) { table_.reserve(n); }
4865 hasher hash_function()
const {
return table_.hash_function(); }
4867 key_equal key_eq()
const {
return table_.key_eq(); }
4870 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
4872 unordered_flat_set<Key, Hash, KeyEqual, Allocator>
const& lhs,
4873 unordered_flat_set<Key, Hash, KeyEqual, Allocator>
const& rhs)
4879 return (lhs.size() == rhs.size()) && ([&] {
4880 for (
auto const& key : lhs) {
4881 auto pos = rhs.find(key);
4882 if ((pos == rhs.end()) || (key != *pos)) {
4890 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
4892 unordered_flat_set<Key, Hash, KeyEqual, Allocator>
const& lhs,
4893 unordered_flat_set<Key, Hash, KeyEqual, Allocator>
const& rhs)
4895 return !(lhs == rhs);
4898 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
4899 void swap(unordered_flat_set<Key, Hash, KeyEqual, Allocator>& lhs,
4900 unordered_flat_set<Key, Hash, KeyEqual, Allocator>& rhs)
4901 noexcept(
noexcept(lhs.swap(rhs)))
4906 template <
class Key,
class Hash,
class KeyEqual,
class Allocator,
4908 typename unordered_flat_set<Key, Hash, KeyEqual, Allocator>::size_type
4909 erase_if(unordered_flat_set<Key, Hash, KeyEqual, Allocator>& set, Pred pred)
4911 return erase_if(set.table_, pred);
4919 template <
class InputIterator,
4921 boost::hash<
typename std::iterator_traits<InputIterator>::value_type>,
4923 std::equal_to<
typename std::iterator_traits<InputIterator>::value_type>,
4924 class Allocator = std::allocator<
4925 typename std::iterator_traits<InputIterator>::value_type>,
4926 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
4927 class = std::enable_if_t<detail::is_hash_v<Hash> >,
4928 class = std::enable_if_t<detail::is_pred_v<Pred> >,
4929 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
4930 unordered_flat_set(InputIterator, InputIterator,
4931 std::size_t = boost::unordered::detail::foa::default_bucket_count,
4932 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
4933 -> unordered_flat_set<
4934 typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
4937 template <
class T,
class Hash = boost::hash<T>,
4938 class Pred = std::equal_to<T>,
class Allocator = std::allocator<T>,
4939 class = std::enable_if_t<detail::is_hash_v<Hash> >,
4940 class = std::enable_if_t<detail::is_pred_v<Pred> >,
4941 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
4942 unordered_flat_set(std::initializer_list<T>,
4943 std::size_t = boost::unordered::detail::foa::default_bucket_count,
4944 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
4945 -> unordered_flat_set<T, Hash, Pred, Allocator>;
4947 template <
class InputIterator,
class Allocator,
4948 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
4949 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
4950 unordered_flat_set(InputIterator, InputIterator, std::size_t, Allocator)
4951 -> unordered_flat_set<
4952 typename std::iterator_traits<InputIterator>::value_type,
4953 boost::hash<
typename std::iterator_traits<InputIterator>::value_type>,
4954 std::equal_to<
typename std::iterator_traits<InputIterator>::value_type>,
4957 template <
class InputIterator,
class Hash,
class Allocator,
4958 class = std::enable_if_t<detail::is_hash_v<Hash> >,
4959 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
4960 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
4962 InputIterator, InputIterator, std::size_t, Hash, Allocator)
4963 -> unordered_flat_set<
4964 typename std::iterator_traits<InputIterator>::value_type, Hash,
4965 std::equal_to<
typename std::iterator_traits<InputIterator>::value_type>,
4968 template <
class T,
class Allocator,
4969 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
4970 unordered_flat_set(std::initializer_list<T>, std::size_t, Allocator)
4971 -> unordered_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
4973 template <
class T,
class Hash,
class Allocator,
4974 class = std::enable_if_t<detail::is_hash_v<Hash> >,
4975 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
4976 unordered_flat_set(std::initializer_list<T>, std::size_t, Hash, Allocator)
4977 -> unordered_flat_set<T, Hash, std::equal_to<T>, Allocator>;
4979 template <
class InputIterator,
class Allocator,
4980 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
4981 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
4982 unordered_flat_set(InputIterator, InputIterator, Allocator)
4983 -> unordered_flat_set<
4984 typename std::iterator_traits<InputIterator>::value_type,
4985 boost::hash<
typename std::iterator_traits<InputIterator>::value_type>,
4986 std::equal_to<
typename std::iterator_traits<InputIterator>::value_type>,
4989 template <
class T,
class Allocator,
4990 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
4991 unordered_flat_set(std::initializer_list<T>, Allocator)
4992 -> unordered_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
5003#ifndef BOOST_UNORDERED_FLAT_MAP_FWD_HPP_INCLUDED
5004#define BOOST_UNORDERED_FLAT_MAP_FWD_HPP_INCLUDED
5009 namespace unordered {
5010 template <
class Key,
class T,
class Hash = boost::hash<Key>,
5011 class KeyEqual = std::equal_to<Key>,
5012 class Allocator = std::allocator<std::pair<
const Key, T> > >
5013 class unordered_flat_map;
5015 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
5017 unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>
const& lhs,
5018 unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>
const& rhs);
5020 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
5022 unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>
const& lhs,
5023 unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>
const& rhs);
5025 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
5026 void swap(unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>& lhs,
5027 unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>& rhs)
5028 noexcept(
noexcept(lhs.swap(rhs)));
5031 using boost::unordered::unordered_flat_map;
5033 using boost::unordered::swap;
5034 using boost::unordered::operator==;
5035 using boost::unordered::operator!=;
5039#ifndef BOOST_ASSERT_SOURCE_LOCATION_HPP_INCLUDED
5040#define BOOST_ASSERT_SOURCE_LOCATION_HPP_INCLUDED
5048#if defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907L
5049# include <source_location>
5055struct source_location
5060 char const * function_;
5061 std::uint_least32_t line_;
5062 std::uint_least32_t column_;
5066 constexpr source_location()
noexcept: file_(
"" ), function_(
"" ), line_( 0 ), column_( 0 )
5070 constexpr source_location(
char const * file, std::uint_least32_t ln,
char const * function, std::uint_least32_t col = 0 )
noexcept: file_( file ), function_( function ), line_( ln ), column_( col )
5074#if defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907L
5076 constexpr source_location( std::source_location
const& loc )
noexcept: file_( loc.file_name() ), function_( loc.function_name() ), line_( loc.line() ), column_( loc.column() )
5082 constexpr char const * file_name()
const noexcept
5087 constexpr char const * function_name()
const noexcept
5092 constexpr std::uint_least32_t line()
const noexcept
5097 constexpr std::uint_least32_t column()
const noexcept
5103# pragma warning( push )
5104# pragma warning( disable: 4996
)
5107#if ( defined(_MSC_VER) && _MSC_VER < 1900
) || ( defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) )
5108# define BOOST_ASSERT_SNPRINTF(buffer, format, arg) std::sprintf(buffer, format, arg)
5110# define BOOST_ASSERT_SNPRINTF(buffer, format, arg) std::snprintf(buffer, sizeof(buffer)/sizeof(buffer[0
]), format, arg)
5113 std::string to_string()
const
5115 unsigned long ln = line();
5119 return "(unknown source location)";
5122 std::string r = file_name();
5129 unsigned long co = column();
5137 char const* fn = function_name();
5141 r +=
" in function '";
5149#undef BOOST_ASSERT_SNPRINTF
5152# pragma warning( pop )
5155 inline friend bool operator==( source_location
const& s1, source_location
const& s2 )
noexcept
5157 return std::strcmp( s1.file_, s2.file_ ) == 0 && std::strcmp( s1.function_, s2.function_ ) == 0 && s1.line_ == s2.line_ && s1.column_ == s2.column_;
5160 inline friend bool operator!=( source_location
const& s1, source_location
const& s2 )
noexcept
5162 return !( s1 == s2 );
5166template<
class E,
class T> std::basic_ostream<E, T> & operator<<( std::basic_ostream<E, T> & os, source_location
const & loc )
5168 os << loc.to_string();
5174#ifdef BOOST_DISABLE_CURRENT_LOCATION
5176# define BOOST_CURRENT_LOCATION ::boost::source_location()
5178#elif defined(BOOST_MSVC) && BOOST_MSVC >= 1926
5182# define BOOST_CURRENT_LOCATION ::boost::source_location(__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION(), __builtin_COLUMN())
5184#elif defined(BOOST_MSVC)
5188# define BOOST_CURRENT_LOCATION_IMPL_1(x) BOOST_CURRENT_LOCATION_IMPL_2(x)
5189# define BOOST_CURRENT_LOCATION_IMPL_2(x) (x##0
/ 10
)
5191# define BOOST_CURRENT_LOCATION ::boost::source_location(__FILE__, BOOST_CURRENT_LOCATION_IMPL_1(__LINE__), "")
5193#elif defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907L
5195# define BOOST_CURRENT_LOCATION ::boost::source_location(::std::source_location::current())
5197#elif defined(BOOST_CLANG
)
5199# define BOOST_CURRENT_LOCATION ::boost::source_location(__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION(), __builtin_COLUMN())
5201#elif defined(BOOST_GCC) && BOOST_GCC >= 70000
5204# define BOOST_CURRENT_LOCATION ::boost::source_location(__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION())
5206#elif defined(BOOST_GCC) && BOOST_GCC >= 50000
5209# define BOOST_CURRENT_LOCATION ::boost::source_location(__FILE__, __LINE__, __PRETTY_FUNCTION__)
5214# define BOOST_CURRENT_LOCATION ::boost::source_location(__FILE__, __LINE__, "")
5224#ifndef BOOST_EXCEPTION_274DA366004E11DCB1DDFE2E56D89593
5225#define BOOST_EXCEPTION_274DA366004E11DCB1DDFE2E56D89593
5227#ifdef BOOST_EXCEPTION_MINI_BOOST
5229namespace boost {
namespace exception_detail {
using std::shared_ptr; } }
5231namespace boost {
template <
class T>
class shared_ptr; }
5232namespace boost {
namespace exception_detail {
using boost::shared_ptr; } }
5235#ifndef BOOST_EXCEPTION_ENABLE_WARNINGS
5236#if __GNUC__
*100
+__GNUC_MINOR__
>301
5237#pragma GCC system_header
5240#pragma clang system_header
5243#pragma warning(push,1
)
5244#pragma warning(disable: 4265
)
5270 refcount_ptr( refcount_ptr
const & x ):
5277 operator=( refcount_ptr
const & x )
5311 if( px_ && px_->release() )
5319 template <
class Tag,
class T>
5322 typedef error_info<
struct throw_function_,
char const *> throw_function;
5323 typedef error_info<
struct throw_file_,
char const *> throw_file;
5324 typedef error_info<
struct throw_line_,
int> throw_line;
5325 typedef error_info<
struct throw_column_,
int> throw_column;
5329 error_info<throw_function_,
char const *>
5332 typedef char const * value_type;
5335 error_info( value_type v ):
5343 error_info<throw_file_,
char const *>
5346 typedef char const * value_type;
5349 error_info( value_type v ):
5357 error_info<throw_line_,
int>
5360 typedef int value_type;
5363 error_info( value_type v ):
5371 error_info<throw_column_,
int>
5374 typedef int value_type;
5377 error_info( value_type v ):
5390 class error_info_base;
5394 error_info_container
5396 virtual char const * diagnostic_information(
char const * )
const = 0;
5397 virtual shared_ptr<error_info_base> get( type_info_
const & )
const = 0;
5398 virtual void set( shared_ptr<error_info_base>
const &, type_info_
const & ) = 0;
5399 virtual void add_ref()
const = 0;
5400 virtual bool release()
const = 0;
5401 virtual refcount_ptr<exception_detail::error_info_container> clone()
const = 0;
5405 ~error_info_container()
noexcept
5414 struct get_info<throw_function>;
5417 struct get_info<throw_file>;
5420 struct get_info<throw_line>;
5423 struct get_info<throw_column>;
5429 struct set_info_rv<throw_function>;
5432 struct set_info_rv<throw_file>;
5435 struct set_info_rv<throw_line>;
5438 struct set_info_rv<throw_column>;
5440 char const * get_diagnostic_information( exception
const &,
char const * );
5442 void copy_boost_exception( exception *, exception
const * );
5444 template <
class E,
class Tag,
class T>
5445 E
const & set_info( E
const &, error_info<Tag,T>
const & );
5448 E
const & set_info( E
const &, throw_function
const & );
5451 E
const & set_info( E
const &, throw_file
const & );
5454 E
const & set_info( E
const &, throw_line
const & );
5457 E
const & set_info( E
const &, throw_column
const & );
5459 boost::source_location get_exception_throw_location( exception
const & );
5468 template <
class Tag>
void set(
typename Tag::type
const & );
5469 template <
class Tag>
typename Tag::type
const * get()
const;
5485 exception( exception
const & x )
noexcept:
5487 throw_function_(x.throw_function_),
5488 throw_file_(x.throw_file_),
5489 throw_line_(x.throw_line_),
5490 throw_column_(x.throw_column_)
5495 virtual ~exception()
noexcept
5501#if (defined(__MWERKS__) && __MWERKS__<=0x3207
) || (defined(_MSC_VER) && _MSC_VER<=1310
)
5507 friend E
const & exception_detail::set_info( E
const &, throw_function
const & );
5510 friend E
const & exception_detail::set_info( E
const &, throw_file
const & );
5513 friend E
const & exception_detail::set_info( E
const &, throw_line
const & );
5516 friend E
const & exception_detail::set_info( E
const &, throw_column
const & );
5518 template <
class E,
class Tag,
class T>
5519 friend E
const & exception_detail::set_info( E
const &, error_info<Tag,T>
const & );
5521 friend char const * exception_detail::get_diagnostic_information( exception
const &,
char const * );
5523 friend boost::source_location exception_detail::get_exception_throw_location( exception
const & );
5526 friend struct exception_detail::get_info;
5527 friend struct exception_detail::get_info<throw_function>;
5528 friend struct exception_detail::get_info<throw_file>;
5529 friend struct exception_detail::get_info<throw_line>;
5530 friend struct exception_detail::get_info<throw_column>;
5532 friend struct exception_detail::set_info_rv;
5533 friend struct exception_detail::set_info_rv<throw_function>;
5534 friend struct exception_detail::set_info_rv<throw_file>;
5535 friend struct exception_detail::set_info_rv<throw_line>;
5536 friend struct exception_detail::set_info_rv<throw_column>;
5537 friend void exception_detail::copy_boost_exception( exception *, exception
const * );
5539 mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_;
5540 mutable char const * throw_function_;
5541 mutable char const * throw_file_;
5542 mutable int throw_line_;
5543 mutable int throw_column_;
5548 ~exception()
noexcept
5557 set_info( E
const & x, throw_function
const & y )
5559 x.throw_function_=y.v_;
5565 set_info( E
const & x, throw_file
const & y )
5573 set_info( E
const & x, throw_line
const & y )
5581 set_info( E
const & x, throw_column
const & y )
5583 x.throw_column_=y.v_;
5589 set_info_rv<throw_column>
5594 set( E
const & x, throw_column && y )
5596 x.throw_column_=y.v_;
5601 inline boost::source_location get_exception_throw_location( exception
const & x )
5603 return boost::source_location(
5604 x.throw_file_? x.throw_file_:
"",
5605 x.throw_line_ >= 0? x.throw_line_: 0,
5606 x.throw_function_? x.throw_function_:
"",
5607 x.throw_column_ >= 0? x.throw_column_: 0
5620 error_info_injector:
5625 error_info_injector( T
const & x ):
5630 ~error_info_injector()
noexcept
5635 struct large_size {
char c[256]; };
5636 large_size dispatch_boost_exception( exception
const * );
5638 struct small_size { };
5639 small_size dispatch_boost_exception(
void const * );
5641 template <
class,
int>
5642 struct enable_error_info_helper;
5646 enable_error_info_helper<T,
sizeof(large_size)>
5653 enable_error_info_helper<T,
sizeof(small_size)>
5655 typedef error_info_injector<T> type;
5660 enable_error_info_return_type
5662 typedef typename enable_error_info_helper<T,
sizeof(exception_detail::dispatch_boost_exception(
static_cast<T *>(0)))>::type type;
5669 exception_detail::enable_error_info_return_type<T>::type
5670 enable_error_info( T
const & x )
5672 typedef typename exception_detail::enable_error_info_return_type<T>::type rt;
5677#ifdef BOOST_NO_EXCEPTIONS
5678 BOOST_NORETURN
void throw_exception(std::exception
const & e);
5690 virtual clone_base
const * clone()
const = 0;
5691 virtual void rethrow()
const = 0;
5694 ~clone_base()
noexcept
5701 copy_boost_exception( exception * a, exception
const * b )
5703 refcount_ptr<error_info_container> data;
5704 if( error_info_container * d=b->data_.get() )
5706 a->throw_file_ = b->throw_file_;
5707 a->throw_line_ = b->throw_line_;
5708 a->throw_function_ = b->throw_function_;
5709 a->throw_column_ = b->throw_column_;
5715 copy_boost_exception(
void *,
void const * )
5724 public virtual clone_base
5726 struct clone_tag { };
5727 clone_impl( clone_impl
const & x, clone_tag ):
5730 copy_boost_exception(
this,&x);
5736 clone_impl( T
const & x ):
5739 copy_boost_exception(
this,&x);
5742 ~clone_impl()
noexcept
5751 return new clone_impl(*
this,clone_tag());
5757#ifdef BOOST_NO_EXCEPTIONS
5758 boost::throw_exception(*
this);
5768 exception_detail::clone_impl<T>
5769 enable_current_exception( T
const & x )
5771 return exception_detail::clone_impl<T>(x);
5775#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
5780#ifndef BOOST_THROW_EXCEPTION_HPP_INCLUDED
5781#define BOOST_THROW_EXCEPTION_HPP_INCLUDED
5785#if defined(_MSC_VER) && (_MSC_VER >= 1020
)
5803#ifdef BOOST_NO_EXCEPTIONS
5805BOOST_NORETURN
void throw_exception( std::exception
const & e );
5806BOOST_NORETURN
void throw_exception( std::exception
const & e, boost::source_location
const & loc );
5815typedef char (&wrapexcept_s1)[ 1 ];
5816typedef char (&wrapexcept_s2)[ 2 ];
5818template<
class T> wrapexcept_s1 wrapexcept_is_convertible( T* );
5819template<
class T> wrapexcept_s2 wrapexcept_is_convertible(
void* );
5821template<
class E,
class B, std::size_t I =
sizeof( wrapexcept_is_convertible<B>(
static_cast< E* >(
nullptr ) ) ) >
struct wrapexcept_add_base;
5823template<
class E,
class B>
struct wrapexcept_add_base<E, B, 1>
5828template<
class E,
class B>
struct wrapexcept_add_base<E, B, 2>
5836 public detail::wrapexcept_add_base<E, boost::exception_detail::clone_base>::type,
5838 public detail::wrapexcept_add_base<E, boost::exception>::type
5845 ~deleter() {
delete p_; }
5850 void copy_from(
void const* )
5854 void copy_from( boost::exception
const* p )
5856 static_cast<boost::exception&>( *
this ) = *p;
5861 explicit wrapexcept( E
const & e ): E( e )
5866 explicit wrapexcept( E
const & e, boost::source_location
const & loc ): E( e )
5870 set_info( *
this, throw_file( loc.file_name() ) );
5871 set_info( *
this, throw_line( loc.line() ) );
5872 set_info( *
this, throw_function( loc.function_name() ) );
5873 set_info( *
this, throw_column( loc.column() ) );
5876 virtual boost::exception_detail::clone_base
const * clone()
const override
5878 wrapexcept * p =
new wrapexcept( *
this );
5879 deleter del = { p };
5881 boost::exception_detail::copy_boost_exception( p,
this );
5887 virtual void rethrow()
const override
5889#ifdef BOOST_NO_EXCEPTIONS
5891 boost::throw_exception( *
this );
5904inline void throw_exception_assert_compatibility( std::exception
const & ) {}
5908#ifndef BOOST_NO_EXCEPTIONS
5910#ifdef BOOST_EXCEPTION_DISABLE
5912template<
class E> BOOST_NORETURN
void throw_exception( E
const & e )
5914 throw_exception_assert_compatibility( e );
5918template<
class E> BOOST_NORETURN
void throw_exception( E
const & e, boost::source_location
const & )
5920 throw_exception_assert_compatibility( e );
5926template<
class E>
BOOST_NORETURN void throw_exception( E
const & e )
5928 throw_exception_assert_compatibility( e );
5929 throw wrapexcept<E>( e );
5932template<
class E>
BOOST_NORETURN void throw_exception( E
const & e, boost::source_location
const & loc )
5934 throw_exception_assert_compatibility( e );
5935 throw wrapexcept<E>( e, loc );
5958 boost::source_location location_;
5960 explicit throw_location( boost::source_location
const & loc ): location_( loc )
5965template<
class E>
class BOOST_SYMBOL_VISIBLE with_throw_location:
public E,
public throw_location
5969 with_throw_location( E
const & e, boost::source_location
const & loc ): E( e ), throw_location( loc )
5973 with_throw_location( E && e, boost::source_location
const & loc ): E( std::move( e ) ), throw_location( loc )
5981#ifndef BOOST_NO_EXCEPTIONS
5985 throw_exception_assert_compatibility( e );
5986 throw detail::with_throw_location<
typename std::decay<E>::type>( std::forward<E>( e ), loc );
5991template<
class E> BOOST_NORETURN
void throw_with_location( E
const & e, boost::source_location
const & loc = BOOST_CURRENT_LOCATION )
5993 boost::throw_exception( e, loc );
6000template<
class E> boost::source_location get_throw_location( E
const & e )
6005 return boost::source_location();
6009 if( detail::throw_location
const* pl =
dynamic_cast< detail::throw_location
const* >( &e ) )
6011 return pl->location_;
6013 else if( boost::exception
const* px =
dynamic_cast< boost::exception
const* >( &e ) )
6015 return exception_detail::get_exception_throw_location( *px );
6019 return boost::source_location();
6032#ifndef BOOST_UNORDERED_UNORDERED_FLAT_MAP_HPP_INCLUDED
6033#define BOOST_UNORDERED_UNORDERED_FLAT_MAP_HPP_INCLUDED
6038 namespace unordered {
6041#pragma warning(push)
6042#pragma warning(disable : 4714
)
6046 template <
class Key,
class T>
struct flat_map_types
6048 using key_type = Key;
6049 using raw_key_type =
typename std::remove_const<Key>::type;
6050 using raw_mapped_type =
typename std::remove_const<T>::type;
6052 using init_type = std::pair<raw_key_type, raw_mapped_type>;
6053 using moved_type = std::pair<raw_key_type&&, raw_mapped_type&&>;
6054 using value_type = std::pair<Key
const, T>;
6056 using element_type = value_type;
6058 static value_type& value_from(element_type& x) {
return x; }
6060 template <
class K,
class V>
6061 static raw_key_type
const& extract(std::pair<K, V>
const& kv)
6066 static moved_type move(init_type& x)
6068 return {std::move(x.first), std::move(x.second)};
6071 static moved_type move(element_type& x)
6074 return {std::move(
const_cast<raw_key_type&>(x.first)),
6075 std::move(
const_cast<raw_mapped_type&>(x.second))};
6078 template <
class A,
class... Args>
6079 static void construct(A& al, init_type* p, Args&&... args)
6081 std::allocator_traits<A>::construct(al, p, std::forward<Args>(args)...);
6084 template <
class A,
class... Args>
6085 static void construct(A& al, value_type* p, Args&&... args)
6087 std::allocator_traits<A>::construct(al, p, std::forward<Args>(args)...);
6090 template <
class A>
static void destroy(A& al, init_type* p)
noexcept
6092 std::allocator_traits<A>::destroy(al, p);
6095 template <
class A>
static void destroy(A& al, value_type* p)
noexcept
6097 std::allocator_traits<A>::destroy(al, p);
6102 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
6103 class unordered_flat_map
6105 using map_types = detail::flat_map_types<Key, T>;
6107 using table_type = detail::foa::table<map_types, Hash, KeyEqual,
6108 typename std::allocator_traits<Allocator>::
template rebind_alloc<
6109 typename map_types::value_type>>;
6113 template <
class K,
class V,
class H,
class KE,
class A,
class Pred>
6114 typename unordered_flat_map<K, V, H, KE, A>::size_type
friend erase_if(
6115 unordered_flat_map<K, V, H, KE, A>& set, Pred pred);
6118 using key_type = Key;
6119 using mapped_type = T;
6120 using value_type =
typename map_types::value_type;
6121 using init_type =
typename map_types::init_type;
6122 using size_type = std::size_t;
6123 using difference_type = std::ptrdiff_t;
6124 using hasher =
typename std::type_identity<Hash>::type;
6125 using key_equal =
typename std::type_identity<KeyEqual>::type;
6126 using allocator_type =
typename std::type_identity<Allocator>::type;
6127 using reference = value_type&;
6128 using const_reference = value_type
const&;
6129 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
6130 using const_pointer =
6131 typename std::allocator_traits<allocator_type>::const_pointer;
6132 using iterator =
typename table_type::iterator;
6133 using const_iterator =
typename table_type::const_iterator;
6135 unordered_flat_map() : unordered_flat_map(0) {}
6137 explicit unordered_flat_map(size_type n, hasher
const& h = hasher(),
6138 key_equal
const& pred = key_equal(),
6139 allocator_type
const& a = allocator_type())
6140 : table_(n, h, pred, a)
6144 unordered_flat_map(size_type n, allocator_type
const& a)
6145 : unordered_flat_map(n, hasher(), key_equal(), a)
6149 unordered_flat_map(size_type n, hasher
const& h, allocator_type
const& a)
6150 : unordered_flat_map(n, h, key_equal(), a)
6154 template <
class InputIterator>
6156 InputIterator f, InputIterator l, allocator_type
const& a)
6157 : unordered_flat_map(f, l, size_type(0), hasher(), key_equal(), a)
6161 explicit unordered_flat_map(allocator_type
const& a)
6162 : unordered_flat_map(0, a)
6166 template <
class Iterator>
6167 unordered_flat_map(Iterator first, Iterator last, size_type n = 0,
6168 hasher
const& h = hasher(), key_equal
const& pred = key_equal(),
6169 allocator_type
const& a = allocator_type())
6170 : unordered_flat_map(n, h, pred, a)
6172 this->insert(first, last);
6175 template <
class Iterator>
6177 Iterator first, Iterator last, size_type n, allocator_type
const& a)
6178 : unordered_flat_map(first, last, n, hasher(), key_equal(), a)
6182 template <
class Iterator>
6183 unordered_flat_map(Iterator first, Iterator last, size_type n,
6184 hasher
const& h, allocator_type
const& a)
6185 : unordered_flat_map(first, last, n, h, key_equal(), a)
6189 unordered_flat_map(unordered_flat_map
const& other) : table_(other.table_)
6194 unordered_flat_map
const& other, allocator_type
const& a)
6195 : table_(other.table_, a)
6199 unordered_flat_map(unordered_flat_map&& other)
6200 noexcept(std::is_nothrow_move_constructible<hasher>::value&&
6201 std::is_nothrow_move_constructible<key_equal>::value&&
6202 std::is_nothrow_move_constructible<allocator_type>::value)
6203 : table_(std::move(other.table_))
6207 unordered_flat_map(unordered_flat_map&& other, allocator_type
const& al)
6208 : table_(std::move(other.table_), al)
6212 unordered_flat_map(std::initializer_list<value_type> ilist,
6213 size_type n = 0, hasher
const& h = hasher(),
6214 key_equal
const& pred = key_equal(),
6215 allocator_type
const& a = allocator_type())
6216 : unordered_flat_map(ilist.begin(), ilist.end(), n, h, pred, a)
6221 std::initializer_list<value_type> il, allocator_type
const& a)
6222 : unordered_flat_map(il, size_type(0), hasher(), key_equal(), a)
6226 unordered_flat_map(std::initializer_list<value_type> init, size_type n,
6227 allocator_type
const& a)
6228 : unordered_flat_map(init, n, hasher(), key_equal(), a)
6232 unordered_flat_map(std::initializer_list<value_type> init, size_type n,
6233 hasher
const& h, allocator_type
const& a)
6234 : unordered_flat_map(init, n, h, key_equal(), a)
6238 ~unordered_flat_map() =
default;
6240 unordered_flat_map& operator=(unordered_flat_map
const& other)
6242 table_ = other.table_;
6246 unordered_flat_map& operator=(unordered_flat_map&& other)
noexcept(
6247 noexcept(std::declval<table_type&>() = std::declval<table_type&&>()))
6249 table_ = std::move(other.table_);
6253 allocator_type get_allocator()
const noexcept
6255 return table_.get_allocator();
6261 iterator begin()
noexcept {
return table_.begin(); }
6262 const_iterator begin()
const noexcept {
return table_.begin(); }
6263 const_iterator cbegin()
const noexcept {
return table_.cbegin(); }
6265 iterator end()
noexcept {
return table_.end(); }
6266 const_iterator end()
const noexcept {
return table_.end(); }
6267 const_iterator cend()
const noexcept {
return table_.cend(); }
6272 [[nodiscard]]
bool empty()
const noexcept
6274 return table_.empty();
6277 size_type size()
const noexcept {
return table_.size(); }
6279 size_type max_size()
const noexcept {
return table_.max_size(); }
6284 void clear()
noexcept { table_.clear(); }
6288 ->
decltype(table_.insert(std::forward<Ty>(value)))
6290 return table_.insert(std::forward<Ty>(value));
6295 return table_.insert(std::move(value));
6300 ->
decltype(table_.insert(std::forward<Ty>(value)).first)
6302 return table_.insert(std::forward<Ty>(value)).first;
6307 return table_.insert(std::move(value)).first;
6310 template <
class InputIterator>
6313 for (
auto pos = first; pos != last; ++pos) {
6314 table_.emplace(*pos);
6318 void insert(std::initializer_list<value_type> ilist)
6320 this->insert(ilist.begin(), ilist.end());
6324 std::pair<iterator,
bool> insert_or_assign(key_type
const& key, M&& obj)
6326 auto ibp = table_.try_emplace(key, std::forward<M>(obj));
6330 ibp.first->second = std::forward<M>(obj);
6335 std::pair<iterator,
bool> insert_or_assign(key_type&& key, M&& obj)
6337 auto ibp = table_.try_emplace(std::move(key), std::forward<M>(obj));
6341 ibp.first->second = std::forward<M>(obj);
6345 template <
class K,
class M>
6346 typename std::enable_if<
6347 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
6348 std::pair<iterator,
bool> >::type
6349 insert_or_assign(K&& k, M&& obj)
6351 auto ibp = table_.try_emplace(std::forward<K>(k), std::forward<M>(obj));
6355 ibp.first->second = std::forward<M>(obj);
6360 iterator insert_or_assign(const_iterator, key_type
const& key, M&& obj)
6362 return this->insert_or_assign(key, std::forward<M>(obj)).first;
6366 iterator insert_or_assign(const_iterator, key_type&& key, M&& obj)
6368 return this->insert_or_assign(std::move(key), std::forward<M>(obj))
6372 template <
class K,
class M>
6373 typename std::enable_if<
6374 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
6376 insert_or_assign(const_iterator, K&& k, M&& obj)
6378 return this->insert_or_assign(std::forward<K>(k), std::forward<M>(obj))
6382 template <
class... Args>
6385 return table_.emplace(std::forward<Args>(args)...);
6388 template <
class... Args>
6391 return table_.emplace(std::forward<Args>(args)...).first;
6394 template <
class... Args>
6396 key_type
const& key, Args&&... args)
6398 return table_.try_emplace(key, std::forward<Args>(args)...);
6401 template <
class... Args>
6403 key_type&& key, Args&&... args)
6405 return table_.try_emplace(std::move(key), std::forward<Args>(args)...);
6408 template <
class K,
class... Args>
6410 boost::unordered::detail::transparent_non_iterable<K,
6411 unordered_flat_map>::value,
6412 std::pair<iterator,
bool> >::type
6413 try_emplace(K&& key, Args&&... args)
6415 return table_.try_emplace(
6416 std::forward<K>(key), std::forward<Args>(args)...);
6419 template <
class... Args>
6421 const_iterator, key_type
const& key, Args&&... args)
6423 return table_.try_emplace(key, std::forward<Args>(args)...).first;
6426 template <
class... Args>
6428 const_iterator, key_type&& key, Args&&... args)
6430 return table_.try_emplace(std::move(key), std::forward<Args>(args)...)
6434 template <
class K,
class... Args>
6436 boost::unordered::detail::transparent_non_iterable<K,
6437 unordered_flat_map>::value,
6439 try_emplace(const_iterator, K&& key, Args&&... args)
6442 .try_emplace(std::forward<K>(key), std::forward<Args>(args)...)
6449 return table_.erase(pos);
6451 iterator erase(const_iterator first, const_iterator last)
6453 while (first != last) {
6454 this->erase(first++);
6456 return iterator{detail::foa::const_iterator_cast_tag{}, last};
6461 return table_.erase(key);
6466 detail::transparent_non_iterable<K, unordered_flat_map>::value,
6470 return table_.erase(key);
6473 void swap(unordered_flat_map& rhs)
noexcept(
6474 noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
6476 table_.swap(rhs.table_);
6479 template <
class H2,
class P2>
6481 unordered_flat_map<key_type, mapped_type, H2, P2, allocator_type>&
6484 table_.merge(source.table_);
6487 template <
class H2,
class P2>
6489 unordered_flat_map<key_type, mapped_type, H2, P2, allocator_type>&&
6492 table_.merge(std::move(source.table_));
6498 mapped_type& at(key_type
const& key)
6500 auto pos = table_.find(key);
6501 if (pos != table_.end()) {
6507 boost::throw_exception(
6508 std::out_of_range(
"key was not found in unordered_flat_map"));
6511 mapped_type
const& at(key_type
const& key)
const
6513 auto pos = table_.find(key);
6514 if (pos != table_.end()) {
6517 boost::throw_exception(
6518 std::out_of_range(
"key was not found in unordered_flat_map"));
6522 typename std::enable_if<
6523 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
6527 auto pos = table_.find(std::forward<K>(key));
6528 if (pos != table_.end()) {
6531 boost::throw_exception(
6532 std::out_of_range(
"key was not found in unordered_flat_map"));
6536 typename std::enable_if<
6537 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
6538 mapped_type
const&>::type
6541 auto pos = table_.find(std::forward<K>(key));
6542 if (pos != table_.end()) {
6545 boost::throw_exception(
6546 std::out_of_range(
"key was not found in unordered_flat_map"));
6551 return table_.try_emplace(key).first->second;
6556 return table_.try_emplace(std::move(key)).first->second;
6560 typename std::enable_if<
6561 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
6565 return table_.try_emplace(std::forward<K>(key)).first->second;
6570 auto pos = table_.find(key);
6571 return pos != table_.end() ? 1 : 0;
6576 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
6577 count(K
const& key)
const
6579 auto pos = table_.find(key);
6580 return pos != table_.end() ? 1 : 0;
6585 return table_.find(key);
6590 return table_.find(key);
6595 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
6599 return table_.find(key);
6604 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
6605 const_iterator>::type
6606 find(K
const& key)
const
6608 return table_.find(key);
6613 return this->find(key) !=
this->end();
6618 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
6620 contains(K
const& key)
const
6622 return this->find(key) !=
this->end();
6625 std::pair<iterator, iterator> equal_range(key_type
const& key)
6627 auto pos = table_.find(key);
6628 if (pos == table_.end()) {
6637 std::pair<const_iterator, const_iterator> equal_range(
6638 key_type
const& key)
const
6640 auto pos = table_.find(key);
6641 if (pos == table_.end()) {
6651 typename std::enable_if<
6652 detail::are_transparent<K, hasher, key_equal>::value,
6653 std::pair<iterator, iterator> >::type
6654 equal_range(K
const& key)
6656 auto pos = table_.find(key);
6657 if (pos == table_.end()) {
6667 typename std::enable_if<
6668 detail::are_transparent<K, hasher, key_equal>::value,
6669 std::pair<const_iterator, const_iterator> >::type
6670 equal_range(K
const& key)
const
6672 auto pos = table_.find(key);
6673 if (pos == table_.end()) {
6685 size_type bucket_count()
const noexcept {
return table_.capacity(); }
6687 float load_factor()
const noexcept {
return table_.load_factor(); }
6689 float max_load_factor()
const noexcept
6691 return table_.max_load_factor();
6694 void max_load_factor(
float) {}
6696 size_type max_load()
const noexcept {
return table_.max_load(); }
6698 void rehash(size_type n) { table_.rehash(n); }
6700 void reserve(size_type n) { table_.reserve(n); }
6705 hasher hash_function()
const {
return table_.hash_function(); }
6707 key_equal key_eq()
const {
return table_.key_eq(); }
6710 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
6712 unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>
const& lhs,
6713 unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>
const& rhs)
6719 return (lhs.size() == rhs.size()) && ([&] {
6720 for (
auto const& kvp : lhs) {
6721 auto pos = rhs.find(kvp.first);
6722 if ((pos == rhs.end()) || (*pos != kvp)) {
6730 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
6732 unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>
const& lhs,
6733 unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>
const& rhs)
6735 return !(lhs == rhs);
6738 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
6739 void swap(unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>& lhs,
6740 unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>& rhs)
6741 noexcept(
noexcept(lhs.swap(rhs)))
6746 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator,
6748 typename unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>::size_type
6750 unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>& map, Pred pred)
6752 return erase_if(map.table_, pred);
6762 template <
typename T>
6764 typename std::iterator_traits<T>::value_type::first_type;
6765 template <
typename T>
6767 typename std::iterator_traits<T>::value_type::second_type;
6768 template <
typename T>
6769 using iter_to_alloc_t =
6770 typename std::pair<iter_key_t<T>
const, iter_val_t<T> >;
6773 template <
class InputIterator,
6775 boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
6777 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
6778 class Allocator = std::allocator<
6779 boost::unordered::detail::iter_to_alloc_t<InputIterator> >,
6780 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
6781 class = std::enable_if_t<detail::is_hash_v<Hash> >,
6782 class = std::enable_if_t<detail::is_pred_v<Pred> >,
6783 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
6784 unordered_flat_map(InputIterator, InputIterator,
6785 std::size_t = boost::unordered::detail::foa::default_bucket_count,
6786 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
6787 -> unordered_flat_map<boost::unordered::detail::iter_key_t<InputIterator>,
6788 boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
6791 template <
class Key,
class T,
6792 class Hash = boost::hash<std::remove_const_t<Key> >,
6793 class Pred = std::equal_to<std::remove_const_t<Key> >,
6794 class Allocator = std::allocator<std::pair<
const Key, T> >,
6795 class = std::enable_if_t<detail::is_hash_v<Hash> >,
6796 class = std::enable_if_t<detail::is_pred_v<Pred> >,
6797 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
6798 unordered_flat_map(std::initializer_list<std::pair<Key, T> >,
6799 std::size_t = boost::unordered::detail::foa::default_bucket_count,
6800 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
6801 -> unordered_flat_map<std::remove_const_t<Key>, T, Hash, Pred,
6804 template <
class InputIterator,
class Allocator,
6805 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
6806 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
6807 unordered_flat_map(InputIterator, InputIterator, std::size_t, Allocator)
6808 -> unordered_flat_map<boost::unordered::detail::iter_key_t<InputIterator>,
6809 boost::unordered::detail::iter_val_t<InputIterator>,
6810 boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
6811 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
6814 template <
class InputIterator,
class Allocator,
6815 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
6816 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
6817 unordered_flat_map(InputIterator, InputIterator, Allocator)
6818 -> unordered_flat_map<boost::unordered::detail::iter_key_t<InputIterator>,
6819 boost::unordered::detail::iter_val_t<InputIterator>,
6820 boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
6821 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
6824 template <
class InputIterator,
class Hash,
class Allocator,
6825 class = std::enable_if_t<detail::is_hash_v<Hash> >,
6826 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
6827 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
6829 InputIterator, InputIterator, std::size_t, Hash, Allocator)
6830 -> unordered_flat_map<boost::unordered::detail::iter_key_t<InputIterator>,
6831 boost::unordered::detail::iter_val_t<InputIterator>, Hash,
6832 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
6835 template <
class Key,
class T,
class Allocator,
6836 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
6837 unordered_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
6838 Allocator) -> unordered_flat_map<std::remove_const_t<Key>, T,
6839 boost::hash<std::remove_const_t<Key> >,
6840 std::equal_to<std::remove_const_t<Key> >, Allocator>;
6842 template <
class Key,
class T,
class Allocator,
6843 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
6844 unordered_flat_map(std::initializer_list<std::pair<Key, T> >, Allocator)
6845 -> unordered_flat_map<std::remove_const_t<Key>, T,
6846 boost::hash<std::remove_const_t<Key> >,
6847 std::equal_to<std::remove_const_t<Key> >, Allocator>;
6849 template <
class Key,
class T,
class Hash,
class Allocator,
6850 class = std::enable_if_t<detail::is_hash_v<Hash> >,
6851 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
6852 unordered_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
6853 Hash, Allocator) -> unordered_flat_map<std::remove_const_t<Key>, T,
6854 Hash, std::equal_to<std::remove_const_t<Key> >, Allocator>;
6862
6863
6864
6865
6866
6867
6869#ifndef BOOST_UNORDERED_DETAIL_FOA_ELEMENT_TYPE_HPP
6870#define BOOST_UNORDERED_DETAIL_FOA_ELEMENT_TYPE_HPP
6884
6885
6886
6887
6888 element_type() =
default;
6889 element_type(value_type* p_):p(p_){}
6890 element_type(element_type
const&) =
delete;
6891 element_type(element_type&& rhs)
noexcept
6897 element_type& operator=(element_type
const&)=
delete;
6898 element_type& operator=(element_type&& rhs)
noexcept
6907 void swap(element_type& rhs)
noexcept
6922
6923
6924
6925
6926
6927
6929#ifndef BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
6930#define BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
6937template <
class Iterator,
class NodeType>
6938struct insert_return_type
6947 [[no_unique_address]] T t_;
6953template <
class TypePolicy,
class Allocator>
6954struct node_handle_base
6957 using type_policy=TypePolicy;
6958 using element_type=
typename type_policy::element_type;
6961 using allocator_type = Allocator;
6964 using node_value_type=
typename type_policy::value_type;
6966 [[no_unique_address]] opt_storage<Allocator> a_;
6969 node_value_type& data()
noexcept
6974 node_value_type
const& data()
const noexcept
6979 element_type& element()
noexcept
6985 element_type
const& element()
const noexcept
6991 Allocator& al()
noexcept
6997 Allocator
const& al()
const noexcept
7003 void emplace(element_type&& x,Allocator a)
7008 new(&a_.t_)Allocator(a);
7019 constexpr node_handle_base()
noexcept:p_{
nullptr}{}
7021 node_handle_base(node_handle_base&& nh)
noexcept
7025 emplace(std::move(nh.p_),nh.al());
7030 node_handle_base& operator=(node_handle_base&& nh)
noexcept
7037 emplace(std::move(nh.p_),std::move(nh.al()));
7042 type_policy::destroy(al(),&p_);
7046 std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value;
7050 type_policy::destroy(al(),&p_);
7052 al()=std::move(nh.al());
7055 p_=std::move(nh.p_);
7063 type_policy::destroy(al(),&p_);
7073 type_policy::destroy(al(),&p_);
7078 allocator_type get_allocator()
const noexcept{
return al();}
7079 explicit operator
bool()
const noexcept{
return !empty();}
7080 [[nodiscard]]
bool empty()
const noexcept{
return p_.p==
nullptr;}
7082 void swap(node_handle_base& nh)
noexcept(
7083 std::allocator_traits<Allocator>::is_always_equal::value||
7084 std::allocator_traits<Allocator>::propagate_on_container_swap::value)
7091 emplace(std::move(nh.p_), nh.al());
7096 nh.emplace(std::move(p_),al());
7100 std::allocator_traits<Allocator>::propagate_on_container_swap::value;
7106 if(pocs)swap(al(),nh.al());
7113 void swap(node_handle_base& lhs,node_handle_base& rhs)
7114 noexcept(
noexcept(lhs.swap(rhs)))
7116 return lhs.swap(rhs);
7130#ifndef BOOST_UNORDERED_NODE_SET_FWD_HPP_INCLUDED
7131#define BOOST_UNORDERED_NODE_SET_FWD_HPP_INCLUDED
7136 namespace unordered {
7137 template <
class Key,
class Hash = boost::hash<Key>,
7138 class KeyEqual = std::equal_to<Key>,
7139 class Allocator = std::allocator<Key> >
7140 class unordered_node_set;
7142 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
7144 unordered_node_set<Key, Hash, KeyEqual, Allocator>
const& lhs,
7145 unordered_node_set<Key, Hash, KeyEqual, Allocator>
const& rhs);
7147 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
7149 unordered_node_set<Key, Hash, KeyEqual, Allocator>
const& lhs,
7150 unordered_node_set<Key, Hash, KeyEqual, Allocator>
const& rhs);
7152 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
7153 void swap(unordered_node_set<Key, Hash, KeyEqual, Allocator>& lhs,
7154 unordered_node_set<Key, Hash, KeyEqual, Allocator>& rhs)
7155 noexcept(
noexcept(lhs.swap(rhs)));
7158 using boost::unordered::unordered_node_set;
7160 using boost::unordered::swap;
7161 using boost::unordered::operator==;
7162 using boost::unordered::operator!=;
7170#ifndef BOOST_UNORDERED_UNORDERED_NODE_SET_HPP_INCLUDED
7171#define BOOST_UNORDERED_UNORDERED_NODE_SET_HPP_INCLUDED
7176 namespace unordered {
7179#pragma warning(push)
7180#pragma warning(disable : 4714
)
7184 template <
class Key>
struct node_set_types
7186 using key_type = Key;
7187 using init_type = Key;
7188 using value_type = Key;
7190 static Key
const& extract(value_type
const& key) {
return key; }
7192 using element_type=foa::element_type<value_type>;
7194 static value_type& value_from(element_type
const& x) {
return *x.p; }
7195 static Key
const& extract(element_type
const& k) {
return *k.p; }
7196 static element_type&& move(element_type& x) {
return std::move(x); }
7197 static value_type&& move(value_type& x) {
return std::move(x); }
7200 static void construct(A& al, element_type* p, element_type
const& copy)
7202 construct(al, p, *copy.p);
7205 template <
typename Allocator>
7206 static void construct(
7207 Allocator&, element_type* p, element_type&& x)
noexcept
7213 template <
class A,
class... Args>
7214 static void construct(A& al, value_type* p, Args&&... args)
7216 std::allocator_traits<A>::construct(al, p, std::forward<Args>(args)...);
7219 template <
class A,
class... Args>
7220 static void construct(A& al, element_type* p, Args&&... args)
7222 p->p = std::to_address(std::allocator_traits<A>::allocate(al, 1));
7225 std::allocator_traits<A>::construct(al, p->p, std::forward<Args>(args)...);
7229 std::allocator_traits<A>::deallocate(al,
7230 std::pointer_traits<
7231 typename std::allocator_traits<A>::pointer>::pointer_to(*p->p),
7238 template <
class A>
static void destroy(A& al, value_type* p)
noexcept
7240 std::allocator_traits<A>::destroy(al, p);
7243 template <
class A>
static void destroy(A& al, element_type* p)
noexcept
7247 std::allocator_traits<A>::deallocate(al,
7248 std::pointer_traits<
typename std::allocator_traits<A>::pointer>::pointer_to(*(p->p)),
7254 template <
class TypePolicy,
class Allocator>
7255 struct node_set_handle
7256 :
public detail::foa::node_handle_base<TypePolicy, Allocator>
7259 using base_type = detail::foa::node_handle_base<TypePolicy, Allocator>;
7261 using typename base_type::type_policy;
7263 template <
class Key,
class Hash,
class Pred,
class Alloc>
7264 friend class boost::unordered::unordered_node_set;
7267 using value_type =
typename TypePolicy::value_type;
7269 constexpr node_set_handle()
noexcept =
default;
7270 node_set_handle(node_set_handle&& nh)
noexcept =
default;
7271 node_set_handle& operator=(node_set_handle&&)
noexcept =
default;
7273 value_type& value()
const
7276 return const_cast<value_type&>(
this->data());
7281 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
7282 class unordered_node_set
7284 using set_types = detail::node_set_types<Key>;
7286 using table_type = detail::foa::table<set_types, Hash, KeyEqual,
7287 typename std::allocator_traits<Allocator>::
template rebind_alloc<
7288 typename set_types::value_type>>;
7292 template <
class K,
class H,
class KE,
class A,
class Pred>
7293 typename unordered_node_set<K, H, KE, A>::size_type
friend erase_if(
7294 unordered_node_set<K, H, KE, A>& set, Pred pred);
7297 using key_type = Key;
7298 using value_type =
typename set_types::value_type;
7299 using init_type =
typename set_types::init_type;
7300 using size_type = std::size_t;
7301 using difference_type = std::ptrdiff_t;
7302 using hasher = Hash;
7303 using key_equal = KeyEqual;
7304 using allocator_type = Allocator;
7305 using reference = value_type&;
7306 using const_reference = value_type
const&;
7307 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
7308 using const_pointer =
7309 typename std::allocator_traits<allocator_type>::const_pointer;
7310 using iterator =
typename table_type::iterator;
7311 using const_iterator =
typename table_type::const_iterator;
7312 using node_type = detail::node_set_handle<set_types,
7313 typename std::allocator_traits<Allocator>::
template rebind_alloc<
7314 typename set_types::value_type>>;
7315 using insert_return_type =
7316 detail::foa::insert_return_type<iterator, node_type>;
7318 unordered_node_set() : unordered_node_set(0) {}
7320 explicit unordered_node_set(size_type n, hasher
const& h = hasher(),
7321 key_equal
const& pred = key_equal(),
7322 allocator_type
const& a = allocator_type())
7323 : table_(n, h, pred, a)
7327 unordered_node_set(size_type n, allocator_type
const& a)
7328 : unordered_node_set(n, hasher(), key_equal(), a)
7332 unordered_node_set(size_type n, hasher
const& h, allocator_type
const& a)
7333 : unordered_node_set(n, h, key_equal(), a)
7337 template <
class InputIterator>
7339 InputIterator f, InputIterator l, allocator_type
const& a)
7340 : unordered_node_set(f, l, size_type(0), hasher(), key_equal(), a)
7344 explicit unordered_node_set(allocator_type
const& a)
7345 : unordered_node_set(0, a)
7349 template <
class Iterator>
7350 unordered_node_set(Iterator first, Iterator last, size_type n = 0,
7351 hasher
const& h = hasher(), key_equal
const& pred = key_equal(),
7352 allocator_type
const& a = allocator_type())
7353 : unordered_node_set(n, h, pred, a)
7355 this->insert(first, last);
7358 template <
class InputIt>
7360 InputIt first, InputIt last, size_type n, allocator_type
const& a)
7361 : unordered_node_set(first, last, n, hasher(), key_equal(), a)
7365 template <
class Iterator>
7366 unordered_node_set(Iterator first, Iterator last, size_type n,
7367 hasher
const& h, allocator_type
const& a)
7368 : unordered_node_set(first, last, n, h, key_equal(), a)
7372 unordered_node_set(unordered_node_set
const& other) : table_(other.table_)
7377 unordered_node_set
const& other, allocator_type
const& a)
7378 : table_(other.table_, a)
7382 unordered_node_set(unordered_node_set&& other)
7383 noexcept(std::is_nothrow_move_constructible<hasher>::value&&
7384 std::is_nothrow_move_constructible<key_equal>::value&&
7385 std::is_nothrow_move_constructible<allocator_type>::value)
7386 : table_(std::move(other.table_))
7390 unordered_node_set(unordered_node_set&& other, allocator_type
const& al)
7391 : table_(std::move(other.table_), al)
7395 unordered_node_set(std::initializer_list<value_type> ilist,
7396 size_type n = 0, hasher
const& h = hasher(),
7397 key_equal
const& pred = key_equal(),
7398 allocator_type
const& a = allocator_type())
7399 : unordered_node_set(ilist.begin(), ilist.end(), n, h, pred, a)
7404 std::initializer_list<value_type> il, allocator_type
const& a)
7405 : unordered_node_set(il, size_type(0), hasher(), key_equal(), a)
7409 unordered_node_set(std::initializer_list<value_type> init, size_type n,
7410 allocator_type
const& a)
7411 : unordered_node_set(init, n, hasher(), key_equal(), a)
7415 unordered_node_set(std::initializer_list<value_type> init, size_type n,
7416 hasher
const& h, allocator_type
const& a)
7417 : unordered_node_set(init, n, h, key_equal(), a)
7421 ~unordered_node_set() =
default;
7423 unordered_node_set& operator=(unordered_node_set
const& other)
7425 table_ = other.table_;
7429 unordered_node_set& operator=(unordered_node_set&& other)
noexcept(
7430 noexcept(std::declval<table_type&>() = std::declval<table_type&&>()))
7432 table_ = std::move(other.table_);
7436 allocator_type get_allocator()
const noexcept
7438 return table_.get_allocator();
7444 iterator begin()
noexcept {
return table_.begin(); }
7445 const_iterator begin()
const noexcept {
return table_.begin(); }
7446 const_iterator cbegin()
const noexcept {
return table_.cbegin(); }
7448 iterator end()
noexcept {
return table_.end(); }
7449 const_iterator end()
const noexcept {
return table_.end(); }
7450 const_iterator cend()
const noexcept {
return table_.cend(); }
7455 [[nodiscard]]
bool empty()
const noexcept
7457 return table_.empty();
7460 size_type size()
const noexcept {
return table_.size(); }
7462 size_type max_size()
const noexcept {
return table_.max_size(); }
7467 void clear()
noexcept { table_.clear(); }
7470 value_type
const& value)
7472 return table_.insert(value);
7477 return table_.insert(std::move(value));
7482 detail::transparent_non_iterable<K, unordered_node_set>::value,
7483 std::pair<iterator,
bool> >::type
7486 return table_.try_emplace(std::forward<K>(k));
7491 return table_.insert(value).first;
7496 return table_.insert(std::move(value)).first;
7501 detail::transparent_non_iterable<K, unordered_node_set>::value,
7503 insert(const_iterator, K&& k)
7505 return table_.try_emplace(std::forward<K>(k)).first;
7508 template <
class InputIterator>
7509 void insert(InputIterator first, InputIterator last)
7511 for (
auto pos = first; pos != last; ++pos) {
7512 table_.emplace(*pos);
7516 void insert(std::initializer_list<value_type> ilist)
7518 this->insert(ilist.begin(), ilist.end());
7521 insert_return_type insert(node_type&& nh)
7524 return {end(),
false, node_type{}};
7529 auto itp = table_.insert(std::move(nh.element()));
7532 return {itp.first,
true, node_type{}};
7534 return {itp.first,
false, std::move(nh)};
7538 iterator insert(const_iterator, node_type&& nh)
7546 auto itp = table_.insert(std::move(nh.element()));
7555 template <
class... Args>
7558 return table_.emplace(std::forward<Args>(args)...);
7561 template <
class... Args>
7564 return table_.emplace(std::forward<Args>(args)...).first;
7569 return table_.erase(pos);
7571 iterator erase(const_iterator first, const_iterator last)
7573 while (first != last) {
7574 this->erase(first++);
7576 return iterator{detail::foa::const_iterator_cast_tag{}, last};
7581 return table_.erase(key);
7586 detail::transparent_non_iterable<K, unordered_node_set>::value,
7590 return table_.erase(key);
7593 void swap(unordered_node_set& rhs)
noexcept(
7594 noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
7596 table_.swap(rhs.table_);
7599 node_type extract(const_iterator pos)
7603 auto elem = table_.extract(pos);
7604 nh.emplace(std::move(elem), get_allocator());
7608 node_type extract(key_type
const& key)
7610 auto pos = find(key);
7611 return pos != end() ? extract(pos) : node_type();
7615 typename std::enable_if<
7616 boost::unordered::detail::transparent_non_iterable<K,
7617 unordered_node_set>::value,
7619 extract(K
const& key)
7621 auto pos = find(key);
7622 return pos != end() ? extract(pos) : node_type();
7625 template <
class H2,
class P2>
7626 void merge(unordered_node_set<key_type, H2, P2, allocator_type>& source)
7628 table_.merge(source.table_);
7631 template <
class H2,
class P2>
7632 void merge(unordered_node_set<key_type, H2, P2, allocator_type>&& source)
7634 table_.merge(std::move(source.table_));
7642 auto pos = table_.find(key);
7643 return pos != table_.end() ? 1 : 0;
7648 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
7649 count(K
const& key)
const
7651 auto pos = table_.find(key);
7652 return pos != table_.end() ? 1 : 0;
7657 return table_.find(key);
7662 return table_.find(key);
7667 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
7671 return table_.find(key);
7676 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
7677 const_iterator>::type
7678 find(K
const& key)
const
7680 return table_.find(key);
7685 return this->find(key) !=
this->end();
7690 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
7692 contains(K
const& key)
const
7694 return this->find(key) !=
this->end();
7697 std::pair<iterator, iterator> equal_range(key_type
const& key)
7699 auto pos = table_.find(key);
7700 if (pos == table_.end()) {
7709 std::pair<const_iterator, const_iterator> equal_range(
7710 key_type
const& key)
const
7712 auto pos = table_.find(key);
7713 if (pos == table_.end()) {
7723 typename std::enable_if<
7724 detail::are_transparent<K, hasher, key_equal>::value,
7725 std::pair<iterator, iterator> >::type
7726 equal_range(K
const& key)
7728 auto pos = table_.find(key);
7729 if (pos == table_.end()) {
7739 typename std::enable_if<
7740 detail::are_transparent<K, hasher, key_equal>::value,
7741 std::pair<const_iterator, const_iterator> >::type
7742 equal_range(K
const& key)
const
7744 auto pos = table_.find(key);
7745 if (pos == table_.end()) {
7757 size_type bucket_count()
const noexcept {
return table_.capacity(); }
7759 float load_factor()
const noexcept {
return table_.load_factor(); }
7761 float max_load_factor()
const noexcept
7763 return table_.max_load_factor();
7766 void max_load_factor(
float) {}
7768 size_type max_load()
const noexcept {
return table_.max_load(); }
7770 void rehash(size_type n) { table_.rehash(n); }
7772 void reserve(size_type n) { table_.reserve(n); }
7777 hasher hash_function()
const {
return table_.hash_function(); }
7779 key_equal key_eq()
const {
return table_.key_eq(); }
7782 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
7784 unordered_node_set<Key, Hash, KeyEqual, Allocator>
const& lhs,
7785 unordered_node_set<Key, Hash, KeyEqual, Allocator>
const& rhs)
7791 return (lhs.size() == rhs.size()) && ([&] {
7792 for (
auto const& key : lhs) {
7793 auto pos = rhs.find(key);
7794 if ((pos == rhs.end()) || (key != *pos)) {
7802 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
7804 unordered_node_set<Key, Hash, KeyEqual, Allocator>
const& lhs,
7805 unordered_node_set<Key, Hash, KeyEqual, Allocator>
const& rhs)
7807 return !(lhs == rhs);
7810 template <
class Key,
class Hash,
class KeyEqual,
class Allocator>
7811 void swap(unordered_node_set<Key, Hash, KeyEqual, Allocator>& lhs,
7812 unordered_node_set<Key, Hash, KeyEqual, Allocator>& rhs)
7813 noexcept(
noexcept(lhs.swap(rhs)))
7818 template <
class Key,
class Hash,
class KeyEqual,
class Allocator,
7820 typename unordered_node_set<Key, Hash, KeyEqual, Allocator>::size_type
7821 erase_if(unordered_node_set<Key, Hash, KeyEqual, Allocator>& set, Pred pred)
7823 return erase_if(set.table_, pred);
7831 template <
class InputIterator,
7833 boost::hash<
typename std::iterator_traits<InputIterator>::value_type>,
7835 std::equal_to<
typename std::iterator_traits<InputIterator>::value_type>,
7836 class Allocator = std::allocator<
7837 typename std::iterator_traits<InputIterator>::value_type>,
7838 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
7839 class = std::enable_if_t<detail::is_hash_v<Hash> >,
7840 class = std::enable_if_t<detail::is_pred_v<Pred> >,
7841 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
7842 unordered_node_set(InputIterator, InputIterator,
7843 std::size_t = boost::unordered::detail::foa::default_bucket_count,
7844 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
7845 -> unordered_node_set<
7846 typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
7849 template <
class T,
class Hash = boost::hash<T>,
7850 class Pred = std::equal_to<T>,
class Allocator = std::allocator<T>,
7851 class = std::enable_if_t<detail::is_hash_v<Hash> >,
7852 class = std::enable_if_t<detail::is_pred_v<Pred> >,
7853 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
7854 unordered_node_set(std::initializer_list<T>,
7855 std::size_t = boost::unordered::detail::foa::default_bucket_count,
7856 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
7857 -> unordered_node_set<T, Hash, Pred, Allocator>;
7859 template <
class InputIterator,
class Allocator,
7860 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
7861 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
7862 unordered_node_set(InputIterator, InputIterator, std::size_t, Allocator)
7863 -> unordered_node_set<
7864 typename std::iterator_traits<InputIterator>::value_type,
7865 boost::hash<
typename std::iterator_traits<InputIterator>::value_type>,
7866 std::equal_to<
typename std::iterator_traits<InputIterator>::value_type>,
7869 template <
class InputIterator,
class Hash,
class Allocator,
7870 class = std::enable_if_t<detail::is_hash_v<Hash> >,
7871 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
7872 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
7874 InputIterator, InputIterator, std::size_t, Hash, Allocator)
7875 -> unordered_node_set<
7876 typename std::iterator_traits<InputIterator>::value_type, Hash,
7877 std::equal_to<
typename std::iterator_traits<InputIterator>::value_type>,
7880 template <
class T,
class Allocator,
7881 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
7882 unordered_node_set(std::initializer_list<T>, std::size_t, Allocator)
7883 -> unordered_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
7885 template <
class T,
class Hash,
class Allocator,
7886 class = std::enable_if_t<detail::is_hash_v<Hash> >,
7887 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
7888 unordered_node_set(std::initializer_list<T>, std::size_t, Hash, Allocator)
7889 -> unordered_node_set<T, Hash, std::equal_to<T>, Allocator>;
7891 template <
class InputIterator,
class Allocator,
7892 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
7893 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
7894 unordered_node_set(InputIterator, InputIterator, Allocator)
7895 -> unordered_node_set<
7896 typename std::iterator_traits<InputIterator>::value_type,
7897 boost::hash<
typename std::iterator_traits<InputIterator>::value_type>,
7898 std::equal_to<
typename std::iterator_traits<InputIterator>::value_type>,
7901 template <
class T,
class Allocator,
7902 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
7903 unordered_node_set(std::initializer_list<T>, Allocator)
7904 -> unordered_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
7915#ifndef BOOST_UNORDERED_NODE_MAP_FWD_HPP_INCLUDED
7916#define BOOST_UNORDERED_NODE_MAP_FWD_HPP_INCLUDED
7921 namespace unordered {
7922 template <
class Key,
class T,
class Hash = boost::hash<Key>,
7923 class KeyEqual = std::equal_to<Key>,
7924 class Allocator = std::allocator<std::pair<
const Key, T> > >
7925 class unordered_node_map;
7927 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
7929 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>
const& lhs,
7930 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>
const& rhs);
7932 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
7934 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>
const& lhs,
7935 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>
const& rhs);
7937 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
7938 void swap(unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& lhs,
7939 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& rhs)
7940 noexcept(
noexcept(lhs.swap(rhs)));
7943 using boost::unordered::unordered_node_map;
7945 using boost::unordered::swap;
7946 using boost::unordered::operator==;
7947 using boost::unordered::operator!=;
7955#ifndef BOOST_UNORDERED_UNORDERED_NODE_MAP_HPP_INCLUDED
7956#define BOOST_UNORDERED_UNORDERED_NODE_MAP_HPP_INCLUDED
7961 namespace unordered {
7964#pragma warning(push)
7965#pragma warning(disable : 4714
)
7969 template <
class Key,
class T>
struct node_map_types
7971 using key_type = Key;
7972 using mapped_type = T;
7973 using raw_key_type =
typename std::remove_const<Key>::type;
7974 using raw_mapped_type =
typename std::remove_const<T>::type;
7976 using init_type = std::pair<raw_key_type, raw_mapped_type>;
7977 using value_type = std::pair<Key
const, T>;
7978 using moved_type = std::pair<raw_key_type&&, raw_mapped_type&&>;
7980 using element_type=foa::element_type<value_type>;
7982 static value_type& value_from(element_type
const& x) {
return *(x.p); }
7984 template <
class K,
class V>
7985 static raw_key_type
const& extract(std::pair<K, V>
const& kv)
7990 static raw_key_type
const& extract(element_type
const& kv)
7995 static element_type&& move(element_type& x) {
return std::move(x); }
7996 static moved_type move(init_type& x)
7998 return {std::move(x.first), std::move(x.second)};
8001 static moved_type move(value_type& x)
8003 return {std::move(
const_cast<raw_key_type&>(x.first)),
8004 std::move(
const_cast<raw_mapped_type&>(x.second))};
8008 static void construct(A&, element_type* p, element_type&& x)
noexcept
8015 static void construct(A& al, element_type* p, element_type
const& copy)
8017 construct(al, p, *copy.p);
8020 template <
class A,
class... Args>
8021 static void construct(A& al, init_type* p, Args&&... args)
8023 std::allocator_traits<A>::construct(al, p, std::forward<Args>(args)...);
8026 template <
class A,
class... Args>
8027 static void construct(A& al, value_type* p, Args&&... args)
8029 std::allocator_traits<A>::construct(al, p, std::forward<Args>(args)...);
8032 template <
class A,
class... Args>
8033 static void construct(A& al, element_type* p, Args&&... args)
8035 p->p = std::to_address(std::allocator_traits<A>::allocate(al, 1));
8038 std::allocator_traits<A>::construct(al, p->p, std::forward<Args>(args)...);
8042 using pointer_type =
typename std::allocator_traits<A>::pointer;
8043 using pointer_traits = std::pointer_traits<pointer_type>;
8045 std::allocator_traits<A>::deallocate(
8046 al, pointer_traits::pointer_to(*(p->p)), 1);
8052 template <
class A>
static void destroy(A& al, value_type* p)
noexcept
8054 std::allocator_traits<A>::destroy(al, p);
8057 template <
class A>
static void destroy(A& al, init_type* p)
noexcept
8059 std::allocator_traits<A>::destroy(al, p);
8062 template <
class A>
static void destroy(A& al, element_type* p)
noexcept
8065 using pointer_type =
typename std::allocator_traits<A>::pointer;
8066 using pointer_traits = std::pointer_traits<pointer_type>;
8069 std::allocator_traits<A>::deallocate(
8070 al, pointer_traits::pointer_to(*(p->p)), 1);
8075 template <
class TypePolicy,
class Allocator>
8076 struct node_map_handle
8077 :
public detail::foa::node_handle_base<TypePolicy, Allocator>
8080 using base_type = detail::foa::node_handle_base<TypePolicy, Allocator>;
8082 using typename base_type::type_policy;
8084 template <
class Key,
class T,
class Hash,
class Pred,
class Alloc>
8085 friend class boost::unordered::unordered_node_map;
8088 using key_type =
typename TypePolicy::key_type;
8089 using mapped_type =
typename TypePolicy::mapped_type;
8091 constexpr node_map_handle()
noexcept =
default;
8092 node_map_handle(node_map_handle&& nh)
noexcept =
default;
8094 node_map_handle& operator=(node_map_handle&&)
noexcept =
default;
8096 key_type& key()
const
8099 return const_cast<key_type&>(
this->data().first);
8102 mapped_type& mapped()
const
8105 return const_cast<mapped_type&>(
this->data().second);
8110 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
8111 class unordered_node_map
8113 using map_types = detail::node_map_types<Key, T>;
8115 using table_type = detail::foa::table<map_types, Hash, KeyEqual,
8116 typename std::allocator_traits<Allocator>::
template rebind_alloc<
8117 std::pair<Key
const, T> >>;
8121 template <
class K,
class V,
class H,
class KE,
class A,
class Pred>
8122 typename unordered_node_map<K, V, H, KE, A>::size_type
friend erase_if(
8123 unordered_node_map<K, V, H, KE, A>& set, Pred pred);
8126 using key_type = Key;
8127 using mapped_type = T;
8128 using value_type =
typename map_types::value_type;
8129 using init_type =
typename map_types::init_type;
8130 using size_type = std::size_t;
8131 using difference_type = std::ptrdiff_t;
8132 using hasher =
typename std::type_identity<Hash>::type;
8133 using key_equal =
typename std::type_identity<KeyEqual>::type;
8134 using allocator_type =
typename std::type_identity<Allocator>::type;
8135 using reference = value_type&;
8136 using const_reference = value_type
const&;
8137 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
8138 using const_pointer =
8139 typename std::allocator_traits<allocator_type>::const_pointer;
8140 using iterator =
typename table_type::iterator;
8141 using const_iterator =
typename table_type::const_iterator;
8142 using node_type = detail::node_map_handle<map_types,
8143 typename std::allocator_traits<Allocator>::
template rebind_alloc<
8144 typename map_types::value_type>>;
8145 using insert_return_type =
8146 detail::foa::insert_return_type<iterator, node_type>;
8148 unordered_node_map() : unordered_node_map(0) {}
8150 explicit unordered_node_map(size_type n, hasher
const& h = hasher(),
8151 key_equal
const& pred = key_equal(),
8152 allocator_type
const& a = allocator_type())
8153 : table_(n, h, pred, a)
8157 unordered_node_map(size_type n, allocator_type
const& a)
8158 : unordered_node_map(n, hasher(), key_equal(), a)
8162 unordered_node_map(size_type n, hasher
const& h, allocator_type
const& a)
8163 : unordered_node_map(n, h, key_equal(), a)
8167 template <
class InputIterator>
8169 InputIterator f, InputIterator l, allocator_type
const& a)
8170 : unordered_node_map(f, l, size_type(0), hasher(), key_equal(), a)
8174 explicit unordered_node_map(allocator_type
const& a)
8175 : unordered_node_map(0, a)
8179 template <
class Iterator>
8180 unordered_node_map(Iterator first, Iterator last, size_type n = 0,
8181 hasher
const& h = hasher(), key_equal
const& pred = key_equal(),
8182 allocator_type
const& a = allocator_type())
8183 : unordered_node_map(n, h, pred, a)
8185 this->insert(first, last);
8188 template <
class Iterator>
8190 Iterator first, Iterator last, size_type n, allocator_type
const& a)
8191 : unordered_node_map(first, last, n, hasher(), key_equal(), a)
8195 template <
class Iterator>
8196 unordered_node_map(Iterator first, Iterator last, size_type n,
8197 hasher
const& h, allocator_type
const& a)
8198 : unordered_node_map(first, last, n, h, key_equal(), a)
8202 unordered_node_map(unordered_node_map
const& other) : table_(other.table_)
8207 unordered_node_map
const& other, allocator_type
const& a)
8208 : table_(other.table_, a)
8212 unordered_node_map(unordered_node_map&& other)
8213 noexcept(std::is_nothrow_move_constructible<hasher>::value&&
8214 std::is_nothrow_move_constructible<key_equal>::value&&
8215 std::is_nothrow_move_constructible<allocator_type>::value)
8216 : table_(std::move(other.table_))
8220 unordered_node_map(unordered_node_map&& other, allocator_type
const& al)
8221 : table_(std::move(other.table_), al)
8225 unordered_node_map(std::initializer_list<value_type> ilist,
8226 size_type n = 0, hasher
const& h = hasher(),
8227 key_equal
const& pred = key_equal(),
8228 allocator_type
const& a = allocator_type())
8229 : unordered_node_map(ilist.begin(), ilist.end(), n, h, pred, a)
8234 std::initializer_list<value_type> il, allocator_type
const& a)
8235 : unordered_node_map(il, size_type(0), hasher(), key_equal(), a)
8239 unordered_node_map(std::initializer_list<value_type> init, size_type n,
8240 allocator_type
const& a)
8241 : unordered_node_map(init, n, hasher(), key_equal(), a)
8245 unordered_node_map(std::initializer_list<value_type> init, size_type n,
8246 hasher
const& h, allocator_type
const& a)
8247 : unordered_node_map(init, n, h, key_equal(), a)
8251 ~unordered_node_map() =
default;
8253 unordered_node_map& operator=(unordered_node_map
const& other)
8255 table_ = other.table_;
8259 unordered_node_map& operator=(unordered_node_map&& other)
noexcept(
8260 noexcept(std::declval<table_type&>() = std::declval<table_type&&>()))
8262 table_ = std::move(other.table_);
8266 allocator_type get_allocator()
const noexcept
8268 return table_.get_allocator();
8274 iterator begin()
noexcept {
return table_.begin(); }
8275 const_iterator begin()
const noexcept {
return table_.begin(); }
8276 const_iterator cbegin()
const noexcept {
return table_.cbegin(); }
8278 iterator end()
noexcept {
return table_.end(); }
8279 const_iterator end()
const noexcept {
return table_.end(); }
8280 const_iterator cend()
const noexcept {
return table_.cend(); }
8285 [[nodiscard]]
bool empty()
const noexcept
8287 return table_.empty();
8290 size_type size()
const noexcept {
return table_.size(); }
8292 size_type max_size()
const noexcept {
return table_.max_size(); }
8297 void clear()
noexcept { table_.clear(); }
8301 ->
decltype(table_.insert(std::forward<Ty>(value)))
8303 return table_.insert(std::forward<Ty>(value));
8308 return table_.insert(std::move(value));
8313 ->
decltype(table_.insert(std::forward<Ty>(value)).first)
8315 return table_.insert(std::forward<Ty>(value)).first;
8320 return table_.insert(std::move(value)).first;
8323 template <
class InputIterator>
8326 for (
auto pos = first; pos != last; ++pos) {
8327 table_.emplace(*pos);
8331 void insert(std::initializer_list<value_type> ilist)
8333 this->insert(ilist.begin(), ilist.end());
8336 insert_return_type insert(node_type&& nh)
8339 return {end(),
false, node_type{}};
8344 auto itp = table_.insert(std::move(nh.element()));
8347 return {itp.first,
true, node_type{}};
8349 return {itp.first,
false, std::move(nh)};
8353 iterator insert(const_iterator, node_type&& nh)
8361 auto itp = table_.insert(std::move(nh.element()));
8371 std::pair<iterator,
bool> insert_or_assign(key_type
const& key, M&& obj)
8373 auto ibp = table_.try_emplace(key, std::forward<M>(obj));
8377 ibp.first->second = std::forward<M>(obj);
8382 std::pair<iterator,
bool> insert_or_assign(key_type&& key, M&& obj)
8384 auto ibp = table_.try_emplace(std::move(key), std::forward<M>(obj));
8388 ibp.first->second = std::forward<M>(obj);
8392 template <
class K,
class M>
8393 typename std::enable_if<
8394 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
8395 std::pair<iterator,
bool> >::type
8396 insert_or_assign(K&& k, M&& obj)
8398 auto ibp = table_.try_emplace(std::forward<K>(k), std::forward<M>(obj));
8402 ibp.first->second = std::forward<M>(obj);
8407 iterator insert_or_assign(const_iterator, key_type
const& key, M&& obj)
8409 return this->insert_or_assign(key, std::forward<M>(obj)).first;
8413 iterator insert_or_assign(const_iterator, key_type&& key, M&& obj)
8415 return this->insert_or_assign(std::move(key), std::forward<M>(obj))
8419 template <
class K,
class M>
8420 typename std::enable_if<
8421 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
8423 insert_or_assign(const_iterator, K&& k, M&& obj)
8425 return this->insert_or_assign(std::forward<K>(k), std::forward<M>(obj))
8429 template <
class... Args>
8432 return table_.emplace(std::forward<Args>(args)...);
8435 template <
class... Args>
8438 return table_.emplace(std::forward<Args>(args)...).first;
8441 template <
class... Args>
8443 key_type
const& key, Args&&... args)
8445 return table_.try_emplace(key, std::forward<Args>(args)...);
8448 template <
class... Args>
8450 key_type&& key, Args&&... args)
8452 return table_.try_emplace(std::move(key), std::forward<Args>(args)...);
8455 template <
class K,
class... Args>
8457 boost::unordered::detail::transparent_non_iterable<K,
8458 unordered_node_map>::value,
8459 std::pair<iterator,
bool> >::type
8460 try_emplace(K&& key, Args&&... args)
8462 return table_.try_emplace(
8463 std::forward<K>(key), std::forward<Args>(args)...);
8466 template <
class... Args>
8468 const_iterator, key_type
const& key, Args&&... args)
8470 return table_.try_emplace(key, std::forward<Args>(args)...).first;
8473 template <
class... Args>
8475 const_iterator, key_type&& key, Args&&... args)
8477 return table_.try_emplace(std::move(key), std::forward<Args>(args)...)
8481 template <
class K,
class... Args>
8483 boost::unordered::detail::transparent_non_iterable<K,
8484 unordered_node_map>::value,
8486 try_emplace(const_iterator, K&& key, Args&&... args)
8489 .try_emplace(std::forward<K>(key), std::forward<Args>(args)...)
8496 return table_.erase(pos);
8498 iterator erase(const_iterator first, const_iterator last)
8500 while (first != last) {
8501 this->erase(first++);
8503 return iterator{detail::foa::const_iterator_cast_tag{}, last};
8508 return table_.erase(key);
8513 detail::transparent_non_iterable<K, unordered_node_map>::value,
8517 return table_.erase(key);
8520 void swap(unordered_node_map& rhs)
noexcept(
8521 noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
8523 table_.swap(rhs.table_);
8526 node_type extract(const_iterator pos)
8530 auto elem = table_.extract(pos);
8531 nh.emplace(std::move(elem), get_allocator());
8535 node_type extract(key_type
const& key)
8537 auto pos = find(key);
8538 return pos != end() ? extract(pos) : node_type();
8542 typename std::enable_if<
8543 boost::unordered::detail::transparent_non_iterable<K,
8544 unordered_node_map>::value,
8546 extract(K
const& key)
8548 auto pos = find(key);
8549 return pos != end() ? extract(pos) : node_type();
8552 template <
class H2,
class P2>
8554 unordered_node_map<key_type, mapped_type, H2, P2, allocator_type>&
8557 table_.merge(source.table_);
8560 template <
class H2,
class P2>
8562 unordered_node_map<key_type, mapped_type, H2, P2, allocator_type>&&
8565 table_.merge(std::move(source.table_));
8571 mapped_type& at(key_type
const& key)
8573 auto pos = table_.find(key);
8574 if (pos != table_.end()) {
8580 boost::throw_exception(
8581 std::out_of_range(
"key was not found in unordered_node_map"));
8584 mapped_type
const& at(key_type
const& key)
const
8586 auto pos = table_.find(key);
8587 if (pos != table_.end()) {
8590 boost::throw_exception(
8591 std::out_of_range(
"key was not found in unordered_node_map"));
8595 typename std::enable_if<
8596 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
8600 auto pos = table_.find(std::forward<K>(key));
8601 if (pos != table_.end()) {
8604 boost::throw_exception(
8605 std::out_of_range(
"key was not found in unordered_node_map"));
8609 typename std::enable_if<
8610 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
8611 mapped_type
const&>::type
8614 auto pos = table_.find(std::forward<K>(key));
8615 if (pos != table_.end()) {
8618 boost::throw_exception(
8619 std::out_of_range(
"key was not found in unordered_node_map"));
8624 return table_.try_emplace(key).first->second;
8629 return table_.try_emplace(std::move(key)).first->second;
8633 typename std::enable_if<
8634 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
8638 return table_.try_emplace(std::forward<K>(key)).first->second;
8643 auto pos = table_.find(key);
8644 return pos != table_.end() ? 1 : 0;
8649 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
8650 count(K
const& key)
const
8652 auto pos = table_.find(key);
8653 return pos != table_.end() ? 1 : 0;
8658 return table_.find(key);
8663 return table_.find(key);
8668 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
8672 return table_.find(key);
8677 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
8678 const_iterator>::type
8679 find(K
const& key)
const
8681 return table_.find(key);
8686 return this->find(key) !=
this->end();
8691 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
8693 contains(K
const& key)
const
8695 return this->find(key) !=
this->end();
8698 std::pair<iterator, iterator> equal_range(key_type
const& key)
8700 auto pos = table_.find(key);
8701 if (pos == table_.end()) {
8710 std::pair<const_iterator, const_iterator> equal_range(
8711 key_type
const& key)
const
8713 auto pos = table_.find(key);
8714 if (pos == table_.end()) {
8724 typename std::enable_if<
8725 detail::are_transparent<K, hasher, key_equal>::value,
8726 std::pair<iterator, iterator> >::type
8727 equal_range(K
const& key)
8729 auto pos = table_.find(key);
8730 if (pos == table_.end()) {
8740 typename std::enable_if<
8741 detail::are_transparent<K, hasher, key_equal>::value,
8742 std::pair<const_iterator, const_iterator> >::type
8743 equal_range(K
const& key)
const
8745 auto pos = table_.find(key);
8746 if (pos == table_.end()) {
8758 size_type bucket_count()
const noexcept {
return table_.capacity(); }
8760 float load_factor()
const noexcept {
return table_.load_factor(); }
8762 float max_load_factor()
const noexcept
8764 return table_.max_load_factor();
8767 void max_load_factor(
float) {}
8769 size_type max_load()
const noexcept {
return table_.max_load(); }
8771 void rehash(size_type n) { table_.rehash(n); }
8773 void reserve(size_type n) { table_.reserve(n); }
8778 hasher hash_function()
const {
return table_.hash_function(); }
8780 key_equal key_eq()
const {
return table_.key_eq(); }
8783 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
8785 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>
const& lhs,
8786 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>
const& rhs)
8792 return (lhs.size() == rhs.size()) && ([&] {
8793 for (
auto const& kvp : lhs) {
8794 auto pos = rhs.find(kvp.first);
8795 if ((pos == rhs.end()) || (*pos != kvp)) {
8803 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
8805 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>
const& lhs,
8806 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>
const& rhs)
8808 return !(lhs == rhs);
8811 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator>
8812 void swap(unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& lhs,
8813 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& rhs)
8814 noexcept(
noexcept(lhs.swap(rhs)))
8819 template <
class Key,
class T,
class Hash,
class KeyEqual,
class Allocator,
8821 typename unordered_node_map<Key, T, Hash, KeyEqual, Allocator>::size_type
8823 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& map, Pred pred)
8825 return erase_if(map.table_, pred);
8835 template <
typename T>
8837 typename std::iterator_traits<T>::value_type::first_type;
8838 template <
typename T>
8840 typename std::iterator_traits<T>::value_type::second_type;
8841 template <
typename T>
8842 using iter_to_alloc_t =
8843 typename std::pair<iter_key_t<T>
const, iter_val_t<T> >;
8846 template <
class InputIterator,
8848 boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
8850 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
8851 class Allocator = std::allocator<
8852 boost::unordered::detail::iter_to_alloc_t<InputIterator> >,
8853 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
8854 class = std::enable_if_t<detail::is_hash_v<Hash> >,
8855 class = std::enable_if_t<detail::is_pred_v<Pred> >,
8856 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
8857 unordered_node_map(InputIterator, InputIterator,
8858 std::size_t = boost::unordered::detail::foa::default_bucket_count,
8859 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
8860 -> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
8861 boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
8864 template <
class Key,
class T,
8865 class Hash = boost::hash<std::remove_const_t<Key> >,
8866 class Pred = std::equal_to<std::remove_const_t<Key> >,
8867 class Allocator = std::allocator<std::pair<
const Key, T> >,
8868 class = std::enable_if_t<detail::is_hash_v<Hash> >,
8869 class = std::enable_if_t<detail::is_pred_v<Pred> >,
8870 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
8871 unordered_node_map(std::initializer_list<std::pair<Key, T> >,
8872 std::size_t = boost::unordered::detail::foa::default_bucket_count,
8873 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
8874 -> unordered_node_map<std::remove_const_t<Key>, T, Hash, Pred,
8877 template <
class InputIterator,
class Allocator,
8878 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
8879 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
8880 unordered_node_map(InputIterator, InputIterator, std::size_t, Allocator)
8881 -> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
8882 boost::unordered::detail::iter_val_t<InputIterator>,
8883 boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
8884 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
8887 template <
class InputIterator,
class Allocator,
8888 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
8889 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
8890 unordered_node_map(InputIterator, InputIterator, Allocator)
8891 -> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
8892 boost::unordered::detail::iter_val_t<InputIterator>,
8893 boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
8894 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
8897 template <
class InputIterator,
class Hash,
class Allocator,
8898 class = std::enable_if_t<detail::is_hash_v<Hash> >,
8899 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
8900 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
8902 InputIterator, InputIterator, std::size_t, Hash, Allocator)
8903 -> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
8904 boost::unordered::detail::iter_val_t<InputIterator>, Hash,
8905 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
8908 template <
class Key,
class T,
class Allocator,
8909 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
8910 unordered_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
8911 Allocator) -> unordered_node_map<std::remove_const_t<Key>, T,
8912 boost::hash<std::remove_const_t<Key> >,
8913 std::equal_to<std::remove_const_t<Key> >, Allocator>;
8915 template <
class Key,
class T,
class Allocator,
8916 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
8917 unordered_node_map(std::initializer_list<std::pair<Key, T> >, Allocator)
8918 -> unordered_node_map<std::remove_const_t<Key>, T,
8919 boost::hash<std::remove_const_t<Key> >,
8920 std::equal_to<std::remove_const_t<Key> >, Allocator>;
8922 template <
class Key,
class T,
class Hash,
class Allocator,
8923 class = std::enable_if_t<detail::is_hash_v<Hash> >,
8924 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
8925 unordered_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
8926 Hash, Allocator) -> unordered_node_map<std::remove_const_t<Key>, T,
8927 Hash, std::equal_to<std::remove_const_t<Key> >, Allocator>;
#define BOOST_ARCH_ARM
Definition boost_unordered.hpp:781
#define BOOST_UNORDERED_STATIC_ASSERT_HASH_PRED(Hash, Pred)
Definition boost_unordered.hpp:760
#define BOOST_CATCH(x)
Definition boost_unordered.hpp:438
#define BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
Definition boost_unordered.hpp:2897
#define BOOST_CURRENT_LOCATION
Definition boost_unordered.hpp:5214
#define BOOST_RETHROW
Definition boost_unordered.hpp:439
#define BOOST_CATCH_END
Definition boost_unordered.hpp:440
#define BOOST_TRY
Definition boost_unordered.hpp:437
#define BOOST_NORETURN
Definition boost_unordered.hpp:140
#define BOOST_FORCEINLINE
Definition boost_unordered.hpp:83
#define BOOST_ASSERT_SNPRINTF(buffer, format, arg)
Definition boost_unordered.hpp:5110
#define BOOST_NOINLINE
Definition boost_unordered.hpp:103
#define BOOST_SYMBOL_VISIBLE
Definition boost_unordered.hpp:112
#define BOOST_ASSERT_MSG(expr, msg)
Definition boost_unordered.hpp:297
#define BOOST_UNLIKELY(x)
Definition boost_unordered.hpp:119
#define BOOST_UNORDERED_ASSUME(cond)
Definition boost_unordered.hpp:743
#define BOOST_LIKELY(x)
Definition boost_unordered.hpp:116
#define BOOST_ASSERT(expr)
Definition boost_unordered.hpp:296