Skip to content

Commit b20953a

Browse files
Add some improvements and tests
1 parent d4a37e2 commit b20953a

File tree

5 files changed

+133
-77
lines changed

5 files changed

+133
-77
lines changed

include/kf/stl/backport/ranges/detail/adjacent_view.h

Lines changed: 96 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4,112 +4,132 @@
44

55
namespace kf
66
{
7-
template <std::ranges::forward_range Range, size_t N>
8-
requires std::ranges::view<Range> && (N > 0) && std::ranges::common_range<Range>
9-
class AdjacentView : public std::ranges::view_interface<AdjacentView<Range, N>>
7+
namespace ranges
108
{
11-
public:
12-
AdjacentView() requires std::default_initializable<Range> = default;
13-
14-
explicit AdjacentView(Range base)
15-
: m_base(std::move(base))
16-
{
17-
}
18-
19-
constexpr auto begin()
9+
template<std::ranges::forward_range Range, size_t N> requires std::ranges::view<Range> && (N > 0) && std::ranges::common_range<Range>
10+
class adjacent_view : public std::ranges::view_interface<adjacent_view<Range, N>>
2011
{
21-
return Iterator{ std::ranges::begin(m_base), std::ranges::end(m_base) };
22-
}
23-
24-
constexpr auto end()
25-
{
26-
return Iterator{ std::ranges::end(m_base) };
27-
}
12+
public:
13+
adjacent_view() requires std::default_initializable<Range> = default;
2814

29-
private:
30-
class Iterator
31-
{
32-
private:
33-
using BaseIterator = std::ranges::iterator_t<Range>;
34-
std::array<BaseIterator, N> m_current{};
15+
explicit adjacent_view(Range base)
16+
: m_base(std::move(base))
17+
{
18+
}
3519

36-
private:
37-
constexpr auto transformToTuple(const decltype(m_current)& arr) const
20+
constexpr auto begin()
3821
{
39-
return arrayToTuple(arr, std::make_index_sequence<N>{});
22+
return iterator{ std::ranges::begin(m_base), std::ranges::end(m_base) };
4023
}
4124

42-
template <std::size_t... I>
43-
constexpr auto arrayToTuple(const decltype(m_current)& arr, std::index_sequence<I...>) const
25+
constexpr auto end()
4426
{
45-
return std::tie((*arr[I])...);
27+
return iterator{ std::ranges::end(m_base) };
4628
}
4729

48-
public:
49-
constexpr Iterator(BaseIterator first, std::ranges::sentinel_t<Range> last)
30+
private:
31+
class iterator
5032
{
51-
m_current.front() = first;
52-
for (size_t i = 1; i < N; ++i)
33+
private:
34+
using range_iterator = std::ranges::iterator_t<Range>;
35+
36+
public:
37+
using iterator_category = std::forward_iterator_tag;
38+
using value_type = void*; // fixme
39+
using difference_type = std::ptrdiff_t;
40+
using pointer = void*; // fixme
41+
using reference = void*; // fixme
42+
43+
constexpr iterator(range_iterator first, std::ranges::sentinel_t<Range> last)
5344
{
54-
std::ranges::advance(first, 1, last);
55-
m_current[i] = first;
45+
m_current.front() = first;
46+
for (size_t i = 1; i < N; ++i)
47+
{
48+
std::ranges::advance(first, 1, last);
49+
m_current[i] = first;
50+
}
5651
}
57-
}
5852

59-
constexpr Iterator(BaseIterator last)
60-
{
61-
if constexpr (!std::ranges::bidirectional_range<Range>)
53+
constexpr iterator(range_iterator last)
54+
{
55+
if constexpr (!std::ranges::bidirectional_range<Range>)
56+
{
57+
m_current.fill(last);
58+
}
59+
else
60+
{
61+
m_current.back() = last;
62+
for (size_t i = 1; i < N; ++i)
63+
{
64+
std::ranges::advance(last, -1, last);
65+
m_current[N - 1 - i] = last;
66+
}
67+
}
68+
}
69+
70+
constexpr auto operator*() const
6271
{
63-
m_current.fill(last);
72+
return transformToTuple(m_current);
6473
}
65-
else
74+
75+
constexpr iterator& operator++()
6676
{
67-
m_current.back() = last;
68-
for (size_t i = 1; i < N; ++i)
77+
for (auto& iter : m_current)
6978
{
70-
std::ranges::advance(last, -1, last);
71-
m_current[N - 1 - i] = last;
79+
++iter;
7280
}
81+
return *this;
7382
}
74-
}
7583

76-
constexpr auto operator*() const
77-
{
78-
return transformToTuple(m_current);
79-
}
84+
constexpr bool operator==(const iterator& other) const
85+
{
86+
return m_current.back() == other.m_current.back();
87+
}
8088

81-
constexpr Iterator& operator++()
82-
{
83-
for (BaseIterator& iter : m_current)
89+
private:
90+
std::array<range_iterator, N> m_current{};
91+
92+
private:
93+
constexpr auto transformToTuple(const decltype(m_current)& arr) const
8494
{
85-
++iter;
95+
return arrayToTuple(arr, std::make_index_sequence<N>{});
8696
}
87-
return *this;
97+
98+
template <std::size_t... I>
99+
constexpr auto arrayToTuple(const decltype(m_current)& arr, std::index_sequence<I...>) const
100+
{
101+
return std::tie((*arr[I])...);
102+
}
103+
};
104+
105+
private:
106+
Range m_base{};
107+
};
108+
109+
template<size_t N>
110+
class adjacent_fn
111+
{
112+
public:
113+
template<std::ranges::viewable_range R> requires std::ranges::forward_range<R>
114+
auto operator()(R&& r) const
115+
{
116+
return adjacent_view<std::views::all_t<R>, N>(std::forward<R>(r));
88117
}
89118

90-
constexpr bool operator==(const Iterator& other) const
119+
// Enables `range | views::adjacent`
120+
template<std::ranges::viewable_range R> requires std::ranges::forward_range<R>
121+
friend auto operator|(R&& r, const adjacent_fn& adj)
91122
{
92-
return m_current.back() == other.m_current.back();
123+
return adj(std::forward<R>(r));
93124
}
94125
};
126+
}
95127

96-
private:
97-
Range m_base{};
98-
};
99-
100-
template <size_t N>
101-
class AdjacentFn
128+
namespace views
102129
{
103-
public:
104-
template <std::ranges::forward_range R>
105-
requires std::ranges::viewable_range<R>
106-
auto operator()(R&& r) const
107-
{
108-
return AdjacentView<std::views::all_t<R>, N>(std::forward<R>(r));
109-
}
110-
};
130+
template<size_t N>
131+
constexpr kf::ranges::adjacent_fn<N> adjacent;
111132

112-
template <size_t N>
113-
constexpr AdjacentFn<N> adjacent;
114-
inline constexpr AdjacentFn<2> pairwise;
133+
inline constexpr kf::ranges::adjacent_fn<2> pairwise;
134+
}
115135
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
#pragma once
2-
#include "detail\adjacent_view.h"
2+
#include "detail/adjacent_view.h"

test/AdjacentView.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#include "pch.h"
2+
#include <kf/stl/backport/ranges/ranges>
3+
4+
SCENARIO("views::adjacent")
5+
{
6+
GIVEN("array with 4 elements: 1,2,3,4")
7+
{
8+
std::array<int, 4> arr = { 1, 2, 3, 4 };
9+
10+
WHEN("create adjacent view for 1 elements")
11+
{
12+
auto view = arr | kf::views::adjacent<1>;
13+
14+
THEN("view contains 4 tuples: (1)(2)(3)(4)")
15+
{
16+
std::array<std::tuple<int>, 4> expected = { { {1}, {2}, {3}, {4} } };
17+
18+
REQUIRE(std::equal(view.begin(), view.end(), expected.begin(), expected.end()));
19+
}
20+
}
21+
22+
WHEN("create adjacent view for 2 elements")
23+
{
24+
auto view = arr | kf::views::adjacent<2>;
25+
26+
THEN("view contains 3 tuples: (1,2)(2,3)(3,4)")
27+
{
28+
std::array<std::tuple<int, int>, 3> expected = { { {1, 2}, {2, 3}, {3, 4} } };
29+
30+
REQUIRE(std::equal(view.begin(), view.end(), expected.begin(), expected.end()));
31+
}
32+
}
33+
}
34+
}

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ find_package(WDK REQUIRED)
3838
wdk_add_driver(kf-test WINVER NTDDI_WIN10 STL
3939
pch.h
4040
pch.cpp
41+
AdjacentView.cpp
4142
HexTest.cpp
4243
Vector.cpp
4344
)

test/pch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22
#include <ntifs.h>
3+
#include <algorithm>
34
#include <array>
45
#include <kmtest/kmtest.h>
56

0 commit comments

Comments
 (0)