Skip to content

Commit

Permalink
Conversions from ranges to containers (C++23)
Browse files Browse the repository at this point in the history
  • Loading branch information
morzhovets committed Nov 3, 2024
1 parent c1c9aca commit 4726585
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 16 deletions.
6 changes: 3 additions & 3 deletions include/momo/HashSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -790,12 +790,12 @@ class HashSet
return pvInsert<false>(ItemTraits::GetKey(extItem.GetItem()), itemCreator);
}

template<typename ArgIterator>
size_t Insert(ArgIterator begin, ArgIterator end)
template<typename ArgIterator, typename ArgSentinel>
size_t Insert(ArgIterator begin, ArgSentinel end)
{
MOMO_STATIC_ASSERT((internal::IsSetArgIterator<ArgIterator, Item>::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<const Item&>(ref)),
Expand Down
2 changes: 1 addition & 1 deletion include/momo/SetUtility.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ namespace internal
};

template<typename ArgIterator, typename Item,
typename ArgReference = typename std::iterator_traits<ArgIterator>::reference>
typename ArgReference = decltype(*std::declval<ArgIterator>())>
struct IsSetArgIterator : public BoolConstant<std::is_reference<ArgReference>::value
&& std::is_same<Item, typename std::decay<ArgReference>::type>::value>
{
Expand Down
6 changes: 5 additions & 1 deletion include/momo/UserSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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]]
Expand Down
104 changes: 93 additions & 11 deletions include/momo/stdish/unordered_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
#include "../HashSet.h"
#include "node_handle.h"

#ifdef MOMO_HAS_CONTAINERS_RANGES
# include <ranges>
#endif

namespace momo
{

Expand Down Expand Up @@ -187,6 +191,42 @@ class unordered_set
{
}

#ifdef MOMO_HAS_CONTAINERS_RANGES
template<std::ranges::input_range Range>
requires std::convertible_to<std::ranges::range_reference_t<Range>, value_type>
unordered_set(std::from_range_t, Range&& values)
{
insert_range(std::forward<Range>(values));
}

template<std::ranges::input_range Range>
requires std::convertible_to<std::ranges::range_reference_t<Range>, 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<Range>(values));
}

template<std::ranges::input_range Range>
requires std::convertible_to<std::ranges::range_reference_t<Range>, 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<Range>(values));
}

template<std::ranges::input_range Range>
requires std::convertible_to<std::ranges::range_reference_t<Range>, 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<Range>(values));
}
#endif // MOMO_HAS_CONTAINERS_RANGES

unordered_set(unordered_set&& right) noexcept
: mHashSet(std::move(right.mHashSet))
{
Expand Down Expand Up @@ -471,14 +511,23 @@ class unordered_set
template<typename Iterator>
void insert(Iterator first, Iterator last)
{
pvInsert(first, last, momo::internal::IsSetArgIterator<Iterator, value_type>());
pvInsertRange(first, last);
}

void insert(std::initializer_list<value_type> values)
{
mHashSet.Insert(values);
}

#ifdef MOMO_HAS_CONTAINERS_RANGES
template<std::ranges::input_range Range>
requires std::convertible_to<std::ranges::range_reference_t<Range>, value_type>
void insert_range(Range&& values)
{
pvInsertRange(std::ranges::begin(values), std::ranges::end(values));
}
#endif // MOMO_HAS_CONTAINERS_RANGES

template<typename... ValueArgs>
std::pair<iterator, bool> emplace(ValueArgs&&... valueArgs)
{
Expand Down Expand Up @@ -646,16 +695,18 @@ class unordered_set
return hashSet;
}

template<typename Iterator>
void pvInsert(Iterator first, Iterator last, std::true_type /*isSetArgIterator*/)
template<typename Iterator, typename Sentinel>
momo::internal::EnableIf<momo::internal::IsSetArgIterator<Iterator, value_type>::value,
void> pvInsertRange(Iterator begin, Sentinel end)
{
mHashSet.Insert(first, last);
mHashSet.Insert(std::move(begin), std::move(end));
}

template<typename Iterator>
void pvInsert(Iterator first, Iterator last, std::false_type /*isSetArgIterator*/)
template<typename Iterator, typename Sentinel>
momo::internal::EnableIf<!momo::internal::IsSetArgIterator<Iterator, value_type>::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);
}

Expand Down Expand Up @@ -712,8 +763,6 @@ class unordered_set_open : public unordered_set<TKey, THashFunc, TEqualFunc, TAl
}
};

#ifdef MOMO_HAS_DEDUCTION_GUIDES

#define MOMO_DECLARE_DEDUCTION_GUIDES(unordered_set) \
template<typename Iterator, \
typename Key = typename std::iterator_traits<Iterator>::value_type> \
Expand Down Expand Up @@ -760,12 +809,45 @@ template<typename Key, typename HashFunc, typename EqualFunc, \
unordered_set(std::initializer_list<Key>, size_t, HashFunc, EqualFunc, Allocator = Allocator()) \
-> unordered_set<Key, HashFunc, EqualFunc, Allocator>;

#define MOMO_DECLARE_DEDUCTION_GUIDES_RANGES(unordered_set) \
template<std::ranges::input_range Range, \
typename Key = std::ranges::range_value_t<Range>> \
unordered_set(std::from_range_t, Range&&) \
-> unordered_set<Key>; \
template<std::ranges::input_range Range, \
typename Key = std::ranges::range_value_t<Range>, \
typename Allocator = std::allocator<Key>, \
typename = decltype(std::declval<Allocator&>().allocate(size_t{}))> \
unordered_set(std::from_range_t, Range&&, size_t, Allocator = Allocator()) \
-> unordered_set<Key, HashCoder<Key>, std::equal_to<Key>, Allocator>; \
template<std::ranges::input_range Range, typename HashFunc, \
typename Key = std::ranges::range_value_t<Range>, \
typename Allocator = std::allocator<Key>, \
typename = decltype(std::declval<HashFunc&>()(std::declval<const Key&>())), \
typename = decltype(std::declval<Allocator&>().allocate(size_t{}))> \
unordered_set(std::from_range_t, Range&&, size_t, HashFunc, Allocator = Allocator()) \
-> unordered_set<Key, HashFunc, std::equal_to<Key>, Allocator>; \
template<std::ranges::input_range Range, typename HashFunc, typename EqualFunc, \
typename Key = std::ranges::range_value_t<Range>, \
typename Allocator = std::allocator<Key>, \
typename = decltype(std::declval<HashFunc&>()(std::declval<const Key&>())), \
typename = decltype(std::declval<EqualFunc&>()(std::declval<const Key&>(), std::declval<const Key&>())), \
typename = decltype(std::declval<Allocator&>().allocate(size_t{}))> \
unordered_set(std::from_range_t, Range&&, size_t, HashFunc, EqualFunc, Allocator = Allocator()) \
-> unordered_set<Key, HashFunc, EqualFunc, Allocator>;

#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

Expand Down

0 comments on commit 4726585

Please sign in to comment.