diff options
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/algorithm.hpp | 31 | ||||
-rw-r--r-- | src/util/algorithm.tpp | 57 | ||||
-rw-r--r-- | src/util/concepts.hpp | 78 |
3 files changed, 166 insertions, 0 deletions
diff --git a/src/util/algorithm.hpp b/src/util/algorithm.hpp new file mode 100644 index 0000000..71a1724 --- /dev/null +++ b/src/util/algorithm.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "util/concepts.hpp" + +#include <concepts> + +template <typename ContainerType, typename Value> +requires Container<ContainerType> +constexpr auto container_find(const ContainerType &container, const Value &value) noexcept + -> typename ContainerType::const_iterator; + +template <typename ContainerType, typename Value> +requires Container<ContainerType> +constexpr auto container_has(const ContainerType &container, const Value &value) noexcept + -> bool; + +template <typename ContainerType, typename Predicate> +requires Container<ContainerType> && HasPushBack<ContainerType> && + std::predicate<Predicate, typename ContainerType::value_type> +constexpr auto +container_filter(const ContainerType &container, Predicate predicate) noexcept + -> ContainerType; + +template <typename ContainerType, typename Predicate> +requires Container<ContainerType> && + std::predicate<Predicate, typename ContainerType::value_type> +constexpr auto +container_filter(const ContainerType &container, Predicate predicate) noexcept + -> ContainerType; + +#include "algorithm.tpp" diff --git a/src/util/algorithm.tpp b/src/util/algorithm.tpp new file mode 100644 index 0000000..00269ed --- /dev/null +++ b/src/util/algorithm.tpp @@ -0,0 +1,57 @@ +#pragma once + +#include "algorithm.hpp" + +#include <algorithm> + +template <typename ContainerType, typename Value> +requires Container<ContainerType> +constexpr auto container_find(const ContainerType &container, const Value &value) noexcept + -> typename ContainerType::const_iterator +{ + return std::find(container.begin(), container.end(), value); +} + +template <typename ContainerType, typename Value> +requires Container<ContainerType> +constexpr auto container_has(const ContainerType &container, const Value &value) noexcept + -> bool +{ + return container_find(container, value) != container.end(); +} + +template <typename ContainerType, typename Predicate> +requires Container<ContainerType> && HasPushBack<ContainerType> && + std::predicate<Predicate, typename ContainerType::value_type> +constexpr auto +container_filter(const ContainerType &container, Predicate predicate) noexcept + -> ContainerType +{ + ContainerType filtered_container; + + std::copy_if( + std::begin(container), + std::end(container), + std::back_inserter(filtered_container), + predicate); + + return filtered_container; +} + +template <typename ContainerType, typename Predicate> +requires Container<ContainerType> && + std::predicate<Predicate, typename ContainerType::value_type> +constexpr auto +container_filter(const ContainerType &container, Predicate predicate) noexcept + -> ContainerType +{ + ContainerType filtered_container; + + std::copy_if( + std::begin(container), + std::end(container), + std::inserter(filtered_container, filtered_container.begin()), + predicate); + + return filtered_container; +} diff --git a/src/util/concepts.hpp b/src/util/concepts.hpp new file mode 100644 index 0000000..928ee39 --- /dev/null +++ b/src/util/concepts.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include <concepts> +#include <iterator> + +/** + * Concept for the Container named requirement. + * + * https://en.cppreference.com/w/cpp/named_req/Container + */ +template <class ContainerType> +concept Container = requires(ContainerType container_a, const ContainerType container_b) +{ + typename ContainerType::value_type; + typename ContainerType::reference; + typename ContainerType::const_reference; + typename ContainerType::iterator; + typename ContainerType::const_iterator; + typename ContainerType::difference_type; + typename ContainerType::size_type; + + requires std::regular<ContainerType>; + requires std::swappable<ContainerType>; + requires std::destructible<typename ContainerType::value_type>; + requires std:: + same_as<typename ContainerType::reference, typename ContainerType::value_type &>; + requires std::same_as< + typename ContainerType::const_reference, + const typename ContainerType::value_type &>; + requires std::forward_iterator<typename ContainerType::iterator>; + requires std::forward_iterator<typename ContainerType::const_iterator>; + requires std::signed_integral<typename ContainerType::difference_type>; + requires std::same_as< + typename ContainerType::difference_type, + typename std::iterator_traits<typename ContainerType::iterator>::difference_type>; + requires std::same_as< + typename ContainerType::difference_type, + typename std::iterator_traits< + typename ContainerType::const_iterator>::difference_type>; + requires std::convertible_to< + typename ContainerType::iterator, + typename ContainerType::const_iterator>; + + { + container_a.begin() + } -> std::same_as<typename ContainerType::iterator>; + { + container_a.end() + } -> std::same_as<typename ContainerType::iterator>; + { + container_b.begin() + } -> std::same_as<typename ContainerType::const_iterator>; + { + container_b.end() + } -> std::same_as<typename ContainerType::const_iterator>; + { + container_a.cbegin() + } -> std::same_as<typename ContainerType::const_iterator>; + { + container_a.cend() + } -> std::same_as<typename ContainerType::const_iterator>; + { + container_a.size() + } -> std::same_as<typename ContainerType::size_type>; + { + container_a.max_size() + } -> std::same_as<typename ContainerType::size_type>; + { + container_a.empty() + } -> std::same_as<bool>; +}; + +template <typename ContainerType> +concept HasPushBack = + requires(ContainerType container, typename ContainerType::value_type value) +{ + container.push_back(value); +}; |