aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Containers/Utilities/MapUtils.h13
-rw-r--r--src/common/Utilities/Containers.h73
2 files changed, 49 insertions, 37 deletions
diff --git a/src/common/Containers/Utilities/MapUtils.h b/src/common/Containers/Utilities/MapUtils.h
index 910f16022a6..88f25c1d28a 100644
--- a/src/common/Containers/Utilities/MapUtils.h
+++ b/src/common/Containers/Utilities/MapUtils.h
@@ -23,10 +23,17 @@
namespace Trinity::Containers
{
+template <typename M>
+concept Map = requires (M)
+{
+ typename M::key_type;
+ typename M::mapped_type;
+};
+
/**
* Returns a pointer to mapped value (or the value itself if map stores pointers)
*/
-template<class M>
+template <Map M>
inline auto MapGetValuePtr(M& map, typename M::key_type const& key)
{
using mapped_type = typename M::mapped_type;
@@ -46,8 +53,8 @@ inline auto MapGetValuePtr(M& map, typename M::key_type const& key)
return itr != map.end() ? std::addressof(itr->second) : nullptr; // value
}
-template<class K, class V, template<class, class, class...> class M, class... Rest>
-void MultimapErasePair(M<K, V, Rest...>& multimap, K const& key, V const& value)
+template <Map M>
+void MultimapErasePair(M& multimap, typename M::key_type const& key, typename M::mapped_type const& value)
{
auto range = multimap.equal_range(key);
for (auto itr = range.first; itr != range.second;)
diff --git a/src/common/Utilities/Containers.h b/src/common/Utilities/Containers.h
index c53dde9d770..563d86449cc 100644
--- a/src/common/Utilities/Containers.h
+++ b/src/common/Utilities/Containers.h
@@ -18,6 +18,7 @@
#ifndef TRINITY_CONTAINERS_H
#define TRINITY_CONTAINERS_H
+#include "Concepts.h"
#include "Define.h"
#include "MapUtils.h"
#include "Random.h"
@@ -63,14 +64,15 @@ namespace Trinity
{
// resizes <container> to have at most <requestedSize> elements
// if it has more than <requestedSize> elements, the elements to keep are selected randomly
- template<class C>
+ template <std::ranges::forward_range C>
void RandomResize(C& container, std::size_t requestedSize)
{
- static_assert(std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<typename C::iterator>::iterator_category>::value, "Invalid container passed to Trinity::Containers::RandomResize");
- if (std::size(container) <= requestedSize)
+ uint32 elementsToProcess = uint32(std::ranges::size(container));
+ if (elementsToProcess <= requestedSize)
return;
- auto keepIt = std::begin(container), curIt = std::begin(container);
- uint32 elementsToKeep = requestedSize, elementsToProcess = std::size(container);
+
+ auto keepIt = std::ranges::begin(container), curIt = std::ranges::begin(container);
+ uint32 elementsToKeep = uint32(requestedSize);
while (elementsToProcess)
{
// this element has chance (elementsToKeep / elementsToProcess) of being kept
@@ -84,15 +86,15 @@ namespace Trinity
++curIt;
--elementsToProcess;
}
- container.erase(keepIt, std::end(container));
+ container.erase(keepIt, std::ranges::end(container));
}
- template<class C, class Predicate>
+ template <std::ranges::forward_range C, invocable_r<bool, std::ranges::range_reference_t<C>> Predicate>
void RandomResize(C& container, Predicate&& predicate, std::size_t requestedSize)
{
//! First use predicate filter
C containerCopy;
- std::copy_if(std::begin(container), std::end(container), std::inserter(containerCopy, std::end(containerCopy)), predicate);
+ std::ranges::copy_if(container, std::inserter(containerCopy, std::ranges::end(containerCopy)), std::forward<Predicate>(predicate));
if (requestedSize)
RandomResize(containerCopy, requestedSize);
@@ -105,11 +107,11 @@ namespace Trinity
*
* Note: container cannot be empty
*/
- template<class C>
- inline auto SelectRandomContainerElement(C const& container) -> typename std::add_const<decltype(*std::begin(container))>::type&
+ template <std::ranges::input_range C>
+ inline auto SelectRandomContainerElement(C const& container) -> std::add_const_t<decltype(*std::ranges::begin(container))>&
{
- auto it = std::begin(container);
- std::advance(it, urand(0, uint32(std::size(container)) - 1));
+ auto it = std::ranges::begin(container);
+ std::ranges::advance(it, urand(0, uint32(std::ranges::size(container)) - 1));
return *it;
}
@@ -122,11 +124,11 @@ namespace Trinity
*
* Note: container cannot be empty
*/
- template<class C>
- inline auto SelectRandomWeightedContainerElement(C const& container, std::span<double> const& weights) -> decltype(std::begin(container))
+ template <std::ranges::input_range C>
+ inline auto SelectRandomWeightedContainerElement(C const& container, std::span<double> const& weights) -> decltype(std::ranges::begin(container))
{
- auto it = std::begin(container);
- std::advance(it, urandweighted(weights.size(), weights.data()));
+ auto it = std::ranges::begin(container);
+ std::ranges::advance(it, urandweighted(weights.size(), weights.data()));
return it;
}
@@ -138,10 +140,10 @@ namespace Trinity
*
* Note: container cannot be empty
*/
- template<class C, class Fn>
- inline auto SelectRandomWeightedContainerElement(C const& container, Fn weightExtractor) -> decltype(std::begin(container))
+ template <std::ranges::input_range C, invocable_r<double, std::ranges::range_reference_t<C>> Fn>
+ inline auto SelectRandomWeightedContainerElement(C const& container, Fn weightExtractor) -> decltype(std::ranges::begin(container))
{
- std::size_t size = std::size(container);
+ std::size_t size = std::ranges::size(container);
std::size_t i = 0;
double* weights = new double[size];
double weightSum = 0.0;
@@ -152,8 +154,8 @@ namespace Trinity
weightSum += weight;
}
- auto it = std::begin(container);
- std::advance(it, weightSum > 0.0 ? urandweighted(size, weights) : urand(0, uint32(std::size(container)) - 1));
+ auto it = std::ranges::begin(container);
+ std::ranges::advance(it, weightSum > 0.0 ? urandweighted(size, weights) : urand(0, uint32(std::ranges::size(container)) - 1));
delete[] weights;
return it;
}
@@ -166,10 +168,10 @@ namespace Trinity
* @param begin Beginning of the range to reorder
* @param end End of the range to reorder
*/
- template<class Iterator>
+ template <std::random_access_iterator Iterator>
inline void RandomShuffle(Iterator begin, Iterator end)
{
- std::shuffle(begin, end, RandomEngine::Instance());
+ std::ranges::shuffle(begin, end, RandomEngine::Instance());
}
/**
@@ -179,10 +181,10 @@ namespace Trinity
*
* @param container Container to reorder
*/
- template<class C>
+ template <std::ranges::random_access_range C>
inline void RandomShuffle(C& container)
{
- RandomShuffle(std::begin(container), std::end(container));
+ RandomShuffle(std::ranges::begin(container), std::ranges::end(container));
}
/**
@@ -197,8 +199,9 @@ namespace Trinity
*
* @return true if containers have a common element, false otherwise.
*/
- template<class Iterator1, class Iterator2>
- inline bool Intersects(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
+ template <std::input_iterator Iterator1, std::sentinel_for<Iterator1> Sentinel1,
+ std::input_iterator Iterator2, std::sentinel_for<Iterator2> Sentinel2>
+ inline constexpr bool Intersects(Iterator1 first1, Sentinel1 last1, Iterator2 first2, Sentinel2 last2)
{
while (first1 != last1 && first2 != last2)
{
@@ -226,8 +229,10 @@ namespace Trinity
*
* @return true if containers have a common element, false otherwise.
*/
- template<class Iterator1, class Iterator2, class Predicate>
- inline bool Intersects(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2, Predicate&& equalPred)
+ template <std::input_iterator Iterator1, std::sentinel_for<Iterator1> Sentinel1,
+ std::input_iterator Iterator2, std::sentinel_for<Iterator2> Sentinel2,
+ invocable_r<bool, std::iter_reference_t<Iterator1>, std::iter_reference_t<Iterator2>> Predicate>
+ inline constexpr bool Intersects(Iterator1 first1, Sentinel1 last1, Iterator2 first2, Sentinel2 last2, Predicate&& equalPred)
{
while (first1 != last1 && first2 != last2)
{
@@ -235,7 +240,7 @@ namespace Trinity
++first1;
else if (*first2 < *first1)
++first2;
- else if (!equalPred(*first1, *first2))
+ else if (!std::invoke(std::forward<Predicate>(equalPred), *first1, *first2))
++first1, ++first2;
else
return true;
@@ -275,8 +280,8 @@ namespace Trinity
}
}
- template <typename Container, typename Predicate>
- void EraseIf(Container& c, Predicate p)
+ template <std::ranges::forward_range Container, invocable_r<bool, std::ranges::range_reference_t<Container>> Predicate>
+ inline void EraseIf(Container& c, Predicate p) requires requires { c.erase(c.begin(), c.end()); }
{
if constexpr (std::is_move_assignable_v<decltype(*c.begin())>)
Impl::EraseIfMoveAssignable(c, std::ref(p));
@@ -291,7 +296,7 @@ namespace Trinity
* This exists as separate overload instead of one function with default argument to allow using
* with vectors of non-default-constructible classes
*/
- template<typename T>
+ template <typename T>
inline decltype(auto) EnsureWritableVectorIndex(std::vector<T>& vec, typename std::vector<T>::size_type i)
{
if (i >= vec.size())
@@ -306,7 +311,7 @@ namespace Trinity
*
* This overload allows specifying what value to pad vector with during .resize
*/
- template<typename T>
+ template <typename T>
inline decltype(auto) EnsureWritableVectorIndex(std::vector<T>& vec, typename std::vector<T>::size_type i, T const& resizeDefault)
{
if (i >= vec.size())