1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#pragma once


#include <cassert><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <iterator><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <concepts><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <ranges><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.


#include "internal/dev_env.hpp"

#include "global/constants.hpp"


namespace uni {

namespace internal {


template<class Super, std::integral SizeType = typename Super::size_type>
struct range_reference {
    using size_type = SizeType;
    using iterator = Super::iterator;

  protected:
    Super *const _super;
    const size_type _begin, _end;

    range_reference(Super *const super, const size_type begin, const size_type end) noexcept(NO_EXCEPT) : _super(super), _begin(begin), _end(end) {}

  public:
    inline auto begin() const noexcept(NO_EXCEPT) { return std::ranges::next(std::ranges::begin(*this->_super), this->_begin); }
    inline auto end() const noexcept(NO_EXCEPT) { return std::ranges::next(std::ranges::begin(*this->_super), this->_end); }

    inline auto size() const noexcept(NO_EXCEPT) { return this->_end - this->_begin; }

    inline auto interval() const noexcept(NO_EXCEPT) { return std::make_pair(this->_begin, this->_end); }

  protected:
    inline auto sub_range(size_type l, size_type r) const noexcept(NO_EXCEPT) {
        l = _super->_positivize_index(l), r = _super->_positivize_index(r);
        assert(0 <= l and l <= r and r <= this->size());

        return range_reference(_super, this->_begin + l, this->_begin + r);
    }

  public:
    template<uni::interval_notation rng = uni::interval_notation::right_open>
    inline auto range(const size_type l, const size_type r) const noexcept(NO_EXCEPT) {
        if constexpr(rng == uni::interval_notation::right_open) return this->sub_range(l, r);
        if constexpr(rng == uni::interval_notation::left_open) return this->sub_range(l+1, r+1);
        if constexpr(rng == uni::interval_notation::open) return this->sub_range(l+1, r);
        if constexpr(rng == uni::interval_notation::closed) return this->sub_range(l, r+1);
    }
    inline auto range() const noexcept(NO_EXCEPT) { return range_reference(this->_begin, this->_end); }

    inline auto operator()(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { return this->sub_range(l, r); }

    inline auto subseq(const size_type p, const size_type c) const noexcept(NO_EXCEPT) { return this->sub_range(p, p+c); }
    inline auto subseq(const size_type p) const noexcept(NO_EXCEPT) { return this->sub_range(p, this->size()); }
};


} // namespace internal

} // namespace uni