diff --git a/include/momo/HashSet.h b/include/momo/HashSet.h index 7e0456ee..458370f8 100644 --- a/include/momo/HashSet.h +++ b/include/momo/HashSet.h @@ -790,12 +790,12 @@ class HashSet return pvInsert(ItemTraits::GetKey(extItem.GetItem()), itemCreator); } - template - size_t Insert(ArgIterator begin, ArgIterator end) + template + size_t Insert(ArgIterator begin, ArgSentinel end) { MOMO_STATIC_ASSERT((internal::IsSetArgIterator::value)); size_t initCount = GetCount(); - for (ArgIterator iter = begin; iter != end; ++iter) + for (ArgIterator iter = std::move(begin); iter != end; ++iter) { auto&& ref = *iter; InsertVar(ItemTraits::GetKey(static_cast(ref)), diff --git a/include/momo/SetUtility.h b/include/momo/SetUtility.h index 757b135d..fcdcf44b 100644 --- a/include/momo/SetUtility.h +++ b/include/momo/SetUtility.h @@ -338,7 +338,7 @@ namespace internal }; template::reference> + typename ArgReference = decltype(*std::declval())> struct IsSetArgIterator : public BoolConstant::value && std::is_same::type>::value> { diff --git a/include/momo/UserSettings.h b/include/momo/UserSettings.h index 48aed6d3..2c92711a 100644 --- a/include/momo/UserSettings.h +++ b/include/momo/UserSettings.h @@ -176,10 +176,14 @@ #endif #if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_three_way_comparison) \ - && defined (__cpp_concepts) + && defined(__cpp_concepts) # define MOMO_HAS_THREE_WAY_COMPARISON #endif +#if defined(__cpp_lib_containers_ranges) +# define MOMO_HAS_CONTAINERS_RANGES +#endif + #ifdef __has_cpp_attribute # if __has_cpp_attribute(nodiscard) # define MOMO_NODISCARD [[nodiscard]] diff --git a/include/momo/stdish/unordered_set.h b/include/momo/stdish/unordered_set.h index 3fab7d4a..56a94ea2 100644 --- a/include/momo/stdish/unordered_set.h +++ b/include/momo/stdish/unordered_set.h @@ -20,6 +20,10 @@ #include "../HashSet.h" #include "node_handle.h" +#ifdef MOMO_HAS_CONTAINERS_RANGES +# include +#endif + namespace momo { @@ -187,6 +191,42 @@ class unordered_set { } +#ifdef MOMO_HAS_CONTAINERS_RANGES + template + requires std::convertible_to, value_type> + unordered_set(std::from_range_t, Range&& values) + { + insert_range(std::forward(values)); + } + + template + requires std::convertible_to, value_type> + unordered_set(std::from_range_t, Range&& values, size_type bucketCount, + const allocator_type& alloc = allocator_type()) + : unordered_set(bucketCount, alloc) + { + insert_range(std::forward(values)); + } + + template + requires std::convertible_to, value_type> + unordered_set(std::from_range_t, Range&& values, size_type bucketCount, const hasher& hashFunc, + const allocator_type& alloc = allocator_type()) + : unordered_set(bucketCount, hashFunc, alloc) + { + insert_range(std::forward(values)); + } + + template + requires std::convertible_to, value_type> + unordered_set(std::from_range_t, Range&& values, size_type bucketCount, const hasher& hashFunc, + const key_equal& equalFunc, const allocator_type& alloc = allocator_type()) + : unordered_set(bucketCount, hashFunc, equalFunc, alloc) + { + insert_range(std::forward(values)); + } +#endif // MOMO_HAS_CONTAINERS_RANGES + unordered_set(unordered_set&& right) noexcept : mHashSet(std::move(right.mHashSet)) { @@ -471,7 +511,7 @@ class unordered_set template void insert(Iterator first, Iterator last) { - pvInsert(first, last, momo::internal::IsSetArgIterator()); + pvInsertRange(first, last); } void insert(std::initializer_list values) @@ -479,6 +519,15 @@ class unordered_set mHashSet.Insert(values); } +#ifdef MOMO_HAS_CONTAINERS_RANGES + template + requires std::convertible_to, value_type> + void insert_range(Range&& values) + { + pvInsertRange(std::ranges::begin(values), std::ranges::end(values)); + } +#endif // MOMO_HAS_CONTAINERS_RANGES + template std::pair emplace(ValueArgs&&... valueArgs) { @@ -646,16 +695,18 @@ class unordered_set return hashSet; } - template - void pvInsert(Iterator first, Iterator last, std::true_type /*isSetArgIterator*/) + template + momo::internal::EnableIf::value, + void> pvInsertRange(Iterator begin, Sentinel end) { - mHashSet.Insert(first, last); + mHashSet.Insert(std::move(begin), std::move(end)); } - template - void pvInsert(Iterator first, Iterator last, std::false_type /*isSetArgIterator*/) + template + momo::internal::EnableIf::value, + void> pvInsertRange(Iterator begin, Sentinel end) { - for (Iterator iter = first; iter != last; ++iter) + for (Iterator iter = std::move(begin); iter != end; ++iter) emplace(*iter); } @@ -712,8 +763,6 @@ class unordered_set_open : public unordered_set::value_type> \ @@ -760,12 +809,45 @@ template, size_t, HashFunc, EqualFunc, Allocator = Allocator()) \ -> unordered_set; +#define MOMO_DECLARE_DEDUCTION_GUIDES_RANGES(unordered_set) \ +template> \ +unordered_set(std::from_range_t, Range&&) \ + -> unordered_set; \ +template, \ + typename Allocator = std::allocator, \ + typename = decltype(std::declval().allocate(size_t{}))> \ +unordered_set(std::from_range_t, Range&&, size_t, Allocator = Allocator()) \ + -> unordered_set, std::equal_to, Allocator>; \ +template, \ + typename Allocator = std::allocator, \ + typename = decltype(std::declval()(std::declval())), \ + typename = decltype(std::declval().allocate(size_t{}))> \ +unordered_set(std::from_range_t, Range&&, size_t, HashFunc, Allocator = Allocator()) \ + -> unordered_set, Allocator>; \ +template, \ + typename Allocator = std::allocator, \ + typename = decltype(std::declval()(std::declval())), \ + typename = decltype(std::declval()(std::declval(), std::declval())), \ + typename = decltype(std::declval().allocate(size_t{}))> \ +unordered_set(std::from_range_t, Range&&, size_t, HashFunc, EqualFunc, Allocator = Allocator()) \ + -> unordered_set; + +#ifdef MOMO_HAS_DEDUCTION_GUIDES MOMO_DECLARE_DEDUCTION_GUIDES(unordered_set) MOMO_DECLARE_DEDUCTION_GUIDES(unordered_set_open) +#endif -#undef MOMO_DECLARE_DEDUCTION_GUIDES +#ifdef MOMO_HAS_CONTAINERS_RANGES +MOMO_DECLARE_DEDUCTION_GUIDES_RANGES(unordered_set) +MOMO_DECLARE_DEDUCTION_GUIDES_RANGES(unordered_set_open) +#endif -#endif // MOMO_HAS_DEDUCTION_GUIDES +#undef MOMO_DECLARE_DEDUCTION_GUIDES +#undef MOMO_DECLARE_DEDUCTION_GUIDES_RANGES } // namespace stdish