-
Notifications
You must be signed in to change notification settings - Fork 73
/
Copy path309.md
114 lines (93 loc) · 3.05 KB
/
309.md
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<details open><summary>Info</summary><p>
* **Did you know that C++20 added support for constexpr std::vector?**
* https://wg21.link/P1004
</p></details><details open><summary>Example</summary><p>
```cpp
template<auto... Ns> consteval auto fn() {
std::vector v{Ns...};
return std::size(v);
}
static_assert(3uz == fn<1, 2, 3>());
```
> https://godbolt.org/z/vx6cPaY8s
</p></details><details open><summary>Puzzle</summary><p>
> **Can you simplify `filter` example by applying best C++ practicies?**
```cpp
#include <tuple>
#include <array>
#include <utility>
#include <vector>
constexpr auto filter(auto t, auto fn) {
// get the size of filtered elements
constexpr auto size = [=] {
std::vector<std::size_t> v{};
std::apply([&, i = 0](auto... ts) mutable {
([&] {
if (fn(ts)) {
v.push_back(i);
}
i++;
}(), ...);
}, t());
return v.size();
}();
// get the array of indecies of filtered elements
constexpr auto values = [=] {
std::array<std::size_t, size> values{};
std::apply([&, x = 0, i = 0](auto... ts) mutable {
([&] {
if (fn(ts)) {
values[x++] = i;
}
i++;
}(), ...);
}, t());
return values;
}();
// convert array indicies to tuple elements
return [=]<auto... Ns>(std::index_sequence<Ns...>) {
return std::tuple{std::get<values[Ns]>(t())...};
}(std::make_index_sequence<size>{});
};
static_assert(std::tuple{1, 2, 3} == filter([] { return std::tuple{1, 2, 3}; }, [](auto) { return true; }));
static_assert(std::tuple{} == filter([] { return std::tuple{1, 2, 3}; }, [](auto) { return false; }));
static_assert(std::tuple{1, 3} == filter([] { return std::tuple{1, 2, 3}; }, [](auto v) { return v != 2; }));
static_assert(std::tuple{2} == filter([] { return std::tuple{1, 2, 3}; }, [](auto v) { return v == 2; }));
```
> https://godbolt.org/z/E7rTGdn7b
</p></details><details><summary>Solutions</summary><p>
```cpp
constexpr auto filter(auto t, auto fn) {
// get the vector of filtered elements
constexpr auto r = [=] {
return std::apply(
[=](auto... ts) {
return [=] {
auto v = std::vector{ts...};
std::erase_if(v, std::not_fn(fn));
return v;
};
},
t());
}();
// convert the vector to a tuple
return [=]<auto... Ns>(std::index_sequence<Ns...>) {
const auto v = r();
return std::tuple{v[Ns]...};
}(std::make_index_sequence<r().size()>{});
}
```
> https://godbolt.org/z/WTMEPs93o
```cpp
constexpr auto filter(auto t, auto fn) {
constexpr auto v = std::apply(
[=](auto... ts) {
auto const ints = {ts...};
return [=] () { return ints | std::views::filter(fn) | std::ranges::to<std::vector>(); };
}, t());
return [=]<auto... Ns>(std::index_sequence<Ns...>) {
return std::tuple{v()[Ns]...};
}(std::make_index_sequence<v().size()>{});
}
```
> https://godbolt.org/z/3z3s4s6h6