143 lines
3.4 KiB
C++
143 lines
3.4 KiB
C++
#ifndef LOGDOCTOR__ARRAYOPS_H
|
|
#define LOGDOCTOR__ARRAYOPS_H
|
|
|
|
|
|
#include <array>
|
|
#include <tuple>
|
|
|
|
|
|
template <typename Array>
|
|
struct Zipperator
|
|
{
|
|
using array_value = typename Array::value_type;
|
|
using array_iterator = typename Array::iterator;
|
|
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using difference_type = std::ptrdiff_t;
|
|
using value_type = std::tuple<array_value&, array_value&>;
|
|
using pointer = std::tuple<array_value&, array_value&>;
|
|
using reference = std::tuple<array_value&, array_value&>;
|
|
|
|
explicit Zipperator( array_iterator l, array_iterator r ) noexcept
|
|
: lit{l},rit{r} {}
|
|
|
|
inline reference operator*()
|
|
{ return std::tuple<array_value&, array_value&>(*lit,*rit); }
|
|
|
|
inline Zipperator& operator++() noexcept
|
|
{ lit++; rit++; return *this; }
|
|
|
|
friend bool operator!=( const Zipperator& lhs, const Zipperator& rhs ) noexcept
|
|
{ return lhs.lit != rhs.lit and lhs.rit != rhs.rit; }
|
|
|
|
private:
|
|
array_iterator lit;
|
|
array_iterator rit;
|
|
};
|
|
|
|
|
|
template <typename Array>
|
|
struct Enumerator
|
|
{
|
|
using array_size_t = typename Array::size_type;
|
|
using array_value = typename Array::value_type;
|
|
using array_iterator = typename Array::const_iterator;
|
|
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using difference_type = std::ptrdiff_t;
|
|
using value_type = std::tuple<array_size_t, array_value>;
|
|
using pointer = std::tuple<array_size_t, array_value>;
|
|
using reference = std::tuple<array_size_t, array_value>;
|
|
|
|
explicit Enumerator( array_iterator a ) noexcept
|
|
: idx{0},iter{a} {}
|
|
|
|
inline reference operator*()
|
|
{ return std::make_tuple(idx,*iter); }
|
|
|
|
inline Enumerator& operator++() noexcept
|
|
{ idx++; iter++; return *this; }
|
|
|
|
friend bool operator!=( const Enumerator& lhs, const Enumerator& rhs ) noexcept
|
|
{ return lhs.iter != rhs.iter; }
|
|
|
|
private:
|
|
array_size_t idx;
|
|
array_iterator iter;
|
|
};
|
|
|
|
|
|
|
|
template <typename Array>
|
|
class ZippedArrays
|
|
{
|
|
Array& larr;
|
|
Array& rarr;
|
|
|
|
public:
|
|
explicit ZippedArrays( Array& l, Array& r )
|
|
: larr{l},rarr{r} {}
|
|
|
|
inline auto begin() noexcept
|
|
{ return Zipperator<Array>(larr.begin(),rarr.begin()); }
|
|
|
|
inline auto end() noexcept
|
|
{ return Zipperator<Array>(larr.end(),rarr.end()); }
|
|
};
|
|
|
|
|
|
template <typename Array>
|
|
class EnumeratdArray
|
|
{
|
|
const Array& arr;
|
|
|
|
public:
|
|
explicit EnumeratdArray( const Array& a )
|
|
: arr{a} {}
|
|
|
|
inline auto begin() noexcept
|
|
{ return Enumerator<Array>(arr.cbegin()); }
|
|
|
|
inline auto end() noexcept
|
|
{ return Enumerator<Array>(arr.cend()); }
|
|
};
|
|
|
|
|
|
//! ArrayOps
|
|
/*!
|
|
Utilities for the arrays
|
|
*/
|
|
namespace ArrayOps
|
|
{
|
|
|
|
//! Zips two arrays
|
|
/*!
|
|
\param l_array The left-side array
|
|
\param r_array The right-side array
|
|
\return An iterator over the two arrays
|
|
\todo Replace with std::views::zip when clang will fully support it
|
|
*/
|
|
template <typename Array>
|
|
inline auto zip( Array& l_array, Array& r_array )
|
|
{
|
|
return ZippedArrays<Array>( l_array, r_array );
|
|
}
|
|
|
|
|
|
//! Enumerates an array
|
|
/*!
|
|
\param array The array
|
|
\return An iterator over the two array along with the index
|
|
\todo Replace with std::views::enumerate when clang will fully support it
|
|
*/
|
|
template <typename Array>
|
|
inline auto enumerate( const Array& array )
|
|
{
|
|
return EnumeratdArray<Array>( array );
|
|
}
|
|
|
|
} // namespace ArrayOps
|
|
|
|
|
|
#endif // LOGDOCTOR__ARRAYOPS_H
|