LogDoctor/logdoctor/utilities/arrays.h

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