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 4726585 commit fff9367
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 17 deletions.
6 changes: 3 additions & 3 deletions include/momo/HashMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -664,12 +664,12 @@ class HashMap
return { PositionProxy(res.position), res.inserted };
}

template<typename ArgIterator,
template<typename ArgIterator, typename ArgSentinel,
typename = decltype(internal::MapPairConverter<ArgIterator>::Convert(*std::declval<ArgIterator>()))>
size_t Insert(ArgIterator begin, ArgIterator end)
size_t Insert(ArgIterator begin, ArgSentinel end)
{
size_t initCount = GetCount();
for (ArgIterator iter = begin; iter != end; ++iter)
for (ArgIterator iter = std::move(begin); iter != end; ++iter)
{
auto pair = internal::MapPairConverter<ArgIterator>::Convert(*iter);
typedef decltype(pair.first) KeyArg;
Expand Down
6 changes: 3 additions & 3 deletions include/momo/MapUtility.h
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,7 @@ namespace internal
std::pair<KeyArg, ValueArg>&& pair) noexcept
{
MOMO_STATIC_ASSERT((std::is_reference<KeyArg>::value && std::is_reference<ValueArg>::value)
|| std::is_reference<typename std::iterator_traits<Iterator>::reference>::value);
|| std::is_reference<decltype(*std::declval<Iterator>())>::value);
return std::pair<KeyArg&&, ValueArg&&>(std::forward<KeyArg>(pair.first),
std::forward<ValueArg>(pair.second));
}
Expand All @@ -990,7 +990,7 @@ namespace internal
const std::pair<KeyArg, ValueArg>& pair) noexcept
{
MOMO_STATIC_ASSERT((std::is_reference<KeyArg>::value && std::is_reference<ValueArg>::value)
|| std::is_reference<typename std::iterator_traits<Iterator>::reference>::value);
|| std::is_reference<decltype(*std::declval<Iterator>())>::value);
return std::pair<const KeyArg&, const ValueArg&>(pair.first, pair.second);
}
};
Expand All @@ -999,7 +999,7 @@ namespace internal
typename KeyArg = decltype((*std::declval<ArgIterator>()).first)>
struct IsMapArgIteratorStd : public BoolConstant<((std::is_reference<KeyArg>::value
&& std::is_reference<decltype((*std::declval<ArgIterator>()).second)>::value)
|| std::is_reference<typename std::iterator_traits<ArgIterator>::reference>::value)
|| std::is_reference<decltype(*std::declval<ArgIterator>())>::value)
&& std::is_same<Key, typename std::decay<KeyArg>::type>::value>
{
};
Expand Down
108 changes: 97 additions & 11 deletions include/momo/stdish/unordered_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
#include "../HashMap.h"
#include "node_handle.h"

#ifdef MOMO_HAS_CONTAINERS_RANGES
# include <ranges>
#endif

namespace momo
{

Expand Down Expand Up @@ -221,6 +225,42 @@ class unordered_map
{
}

#ifdef MOMO_HAS_CONTAINERS_RANGES
template<std::ranges::input_range Range>
requires std::convertible_to<std::ranges::range_reference_t<Range>, value_type>
unordered_map(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_map(std::from_range_t, Range&& values, size_type bucketCount,
const allocator_type& alloc = allocator_type())
: unordered_map(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_map(std::from_range_t, Range&& values, size_type bucketCount, const hasher& hashFunc,
const allocator_type& alloc = allocator_type())
: unordered_map(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_map(std::from_range_t, Range&& values, size_type bucketCount, const hasher& hashFunc,
const key_equal& equalFunc, const allocator_type& alloc = allocator_type())
: unordered_map(bucketCount, hashFunc, equalFunc, alloc)
{
insert_range(std::forward<Range>(values));
}
#endif // MOMO_HAS_CONTAINERS_RANGES

unordered_map(unordered_map&& right) noexcept
: mHashMap(std::move(right.mHashMap))
{
Expand Down Expand Up @@ -558,14 +598,23 @@ class unordered_map
template<typename Iterator>
void insert(Iterator first, Iterator last)
{
pvInsert(first, last, momo::internal::IsMapArgIteratorStd<Iterator, key_type>());
pvInsertRange(first, last);
}

void insert(std::initializer_list<value_type> values)
{
mHashMap.Insert(values.begin(), values.end());
}

#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

std::pair<iterator, bool> emplace()
{
return pvEmplace(nullptr, std::tuple<>(), std::tuple<>());
Expand Down Expand Up @@ -947,16 +996,18 @@ class unordered_map
}
#endif // MOMO_USE_UNORDERED_HINT_ITERATORS

template<typename Iterator>
void pvInsert(Iterator first, Iterator last, std::true_type /*isMapArgIterator*/)
template<typename Iterator, typename Sentinel>
momo::internal::EnableIf<momo::internal::IsMapArgIteratorStd<Iterator, key_type>::value,
void> pvInsertRange(Iterator begin, Sentinel end)
{
mHashMap.Insert(first, last);
mHashMap.Insert(std::move(begin), std::move(end));
}

template<typename Iterator>
void pvInsert(Iterator first, Iterator last, std::false_type /*isMapArgIterator*/)
template<typename Iterator, typename Sentinel>
momo::internal::EnableIf<!momo::internal::IsMapArgIteratorStd<Iterator, key_type>::value,
void> pvInsertRange(Iterator begin, Sentinel end)
{
for (Iterator iter = first; iter != last; ++iter)
for (Iterator iter = std::move(begin); iter != end; ++iter)
insert(*iter);
}

Expand Down Expand Up @@ -1029,8 +1080,6 @@ class unordered_map_open : public unordered_map<TKey, TMapped, THashFunc, TEqual
}
};

#ifdef MOMO_HAS_DEDUCTION_GUIDES

#define MOMO_DECLARE_DEDUCTION_GUIDES(unordered_map) \
template<typename Iterator, \
typename Key = std::remove_const_t<typename std::iterator_traits<Iterator>::value_type::first_type>, \
Expand Down Expand Up @@ -1081,12 +1130,49 @@ template<typename Key, typename Mapped, typename HashFunc, typename EqualFunc, \
unordered_map(std::initializer_list<std::pair<Key, Mapped>>, size_t, HashFunc, EqualFunc, Allocator = Allocator()) \
-> unordered_map<Key, Mapped, HashFunc, EqualFunc, Allocator>;

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

#ifdef MOMO_HAS_DEDUCTION_GUIDES
MOMO_DECLARE_DEDUCTION_GUIDES(unordered_map)
MOMO_DECLARE_DEDUCTION_GUIDES(unordered_map_open)
#endif

#undef MOMO_DECLARE_DEDUCTION_GUIDES
#ifdef MOMO_HAS_CONTAINERS_RANGES
MOMO_DECLARE_DEDUCTION_GUIDES_RANGES(unordered_map)
MOMO_DECLARE_DEDUCTION_GUIDES_RANGES(unordered_map_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 fff9367

Please sign in to comment.