const_container/include/helper.h

67 lines
2.6 KiB
C++

//
// Created by Patrick Maschek on 24.12.2023.
//
#ifndef CONST_CONTAINER_HELPER_H_
#define CONST_CONTAINER_HELPER_H_
#include <cstddef>
#include <iterator>
#include <stdexcept>
#include <string>
namespace cc::helper {
template<typename T, std::size_t N>
constexpr std::size_t array_size(const T(&)[N]) { return N; }
template<std::input_or_output_iterator InputIt1, std::input_or_output_iterator InputIt2>
requires std::is_same_v<typename std::iterator_traits<InputIt1>::value_type, typename std::iterator_traits<InputIt2>::value_type>
&& std::indirectly_writable<InputIt1, typename std::iterator_traits<InputIt2>::value_type> && std::indirectly_readable<InputIt1>
&& std::indirectly_writable<InputIt2, typename std::iterator_traits<InputIt1>::value_type> && std::indirectly_readable<InputIt2>
constexpr void swap_iter_range(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
{
auto dist1 = std::distance(first1, last1);
auto dist2 = std::distance(first2, last2);
if (dist1 == dist2) {
std::swap_ranges(first1, last1, first2);
return;
}
auto swap_dist = std::min(dist1, dist2);
std::swap_ranges(first1, std::next(first1, swap_dist), first2);
std::advance(first1, swap_dist);
std::advance(first2, swap_dist);
if (dist1 < dist2) {
std::move(first2, last2, last1);
} else {
std::move(first1, last1, last2);
}
}
template<std::input_or_output_iterator InputIt1, std::input_or_output_iterator InputIt2>
requires std::is_same_v<typename std::iterator_traits<InputIt1>::value_type, typename std::iterator_traits<InputIt2>::value_type>
&& std::indirectly_writable<InputIt1, typename std::iterator_traits<InputIt2>::value_type> && std::indirectly_readable<InputIt1>
&& std::indirectly_writable<InputIt2, typename std::iterator_traits<InputIt1>::value_type> && std::indirectly_readable<InputIt2>
constexpr void swap(InputIt1 first1, InputIt1 last1, InputIt1 end1, InputIt2 first2, InputIt2 last2, InputIt2 end2)
{
auto max_dist = std::min(std::distance(first1, end1), std::distance(first2, end2));
auto dist1 = std::distance(first1, last1);
auto dist2 = std::distance(first2, last2);
if (max_dist < dist1 || max_dist < dist2) throw std::invalid_argument("Distance between iterators does not fit in between other "
"(Range 1: " + std::to_string(dist1) + "/" + std::to_string(std::distance(first1, end1)) + ", " +
"Range 2: " + std::to_string(dist2) + "/" + std::to_string(std::distance(first2, end2)) + ")");
swap_iter_range(first1, last1, first2, last2);
}
}; // cc
#endif //CONST_CONTAINER_HELPER_H_