-
Notifications
You must be signed in to change notification settings - Fork 73
/
Copy path201.md
140 lines (103 loc) · 3.23 KB
/
201.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<details open><summary>Info</summary><p>
* **Did you know that `sizeof` operator can be used for efficient math computation?**
* http://eel.is/c++draft/expr.sizeof
</p></details><details open><summary>Example</summary><p>
```cpp
template<auto n> consteval auto sqr() {
return sizeof(std::byte[n][n]);
}
static_assert(2*2 == sqr<2>());
static_assert(10*10 == sqr<10>());
```
> https://godbolt.org/z/bsvKKT
</p></details><details open><summary>Puzzle</summary><p>
* **Can you implement an `exponent` variable template which calculates the {x^n} only by leveraging `sizeof` operator?**
```cpp
template<auto X, auto N>
constexpr auto exponent = 0;
static_assert(1 == exponent<1, 1>);
static_assert(1*1*1*1 == exponent<1, 4>);
static_assert(2*2 == exponent<2, 2>);
static_assert(4*4 == exponent<4, 2>);
static_assert(5*5*5*5 == exponent<5, 4>);
static_assert(10*10*10 == exponent<10, 3>);
static_assert(0 != exponent<1, 2>);
static_assert(1 != exponent<2, 1>);
static_assert(2 != exponent<2, 2>);
```
> https://godbolt.org/z/qqoGxs
</p></details><details><summary>Solutions</summary><p>
```cpp
template<auto X, auto N>
constexpr auto dimensions(auto x) {
if constexpr (N == 0) {
return x;
} else {
return dimensions<X,N-1>(std::array<decltype(x), X>{});
}
}
template<auto X, auto N>
constexpr auto exponent = sizeof(decltype(dimensions<X,N>(std::byte{})));
```
> https://godbolt.org/z/j7Yh46
```cpp
template <auto X, auto Y>
constexpr auto mult = sizeof(char[X][Y]);
template<auto X, auto N>
constexpr auto exponent = ((N & 1) == 0) ? mult<exponent<X, N/2>, exponent<X, N/2>> : mult<X, exponent<X, N-1>>;
template<auto X>
constexpr auto exponent<X, 0> = 1;
```
> https://godbolt.org/z/ve6d1v
```cpp
template<auto X, auto N>
constexpr auto exponent = sizeof( char[N % 2 ? X : 1][exponent<X, N / 2>][exponent<X, N / 2>] );
template<auto X>
constexpr auto exponent<X, 0> = 1;
```
> https://godbolt.org/z/xh6xvf
```cpp
template<size_t x, size_t n>
constexpr auto carr() {
if constexpr(n==0)
return std::array<char, 1>{};
else
return std::array< decltype(carr<x,n-1>()) , x>{};
}
template<auto x, auto n>
constexpr auto exponent = sizeof(carr<x,n>());
```
> https://godbolt.org/z/19Yvs9
```cpp
namespace detail {
template <auto Val>
[[nodiscard]] consteval auto mult() {
return Val;
}
template <auto Val1, auto Val2, auto... Vals>
[[nodiscard]] consteval auto mult() {
return mult<sizeof(std::byte[Val1][Val2]), Vals...>();
}
[[nodiscard]] consteval auto only_first(auto first, auto...) {
return first;
}
template <auto Base, auto... PowerSequence>
[[nodiscard]] consteval auto exponent_impl(std::index_sequence<PowerSequence...>) {
return mult<only_first(Base, PowerSequence)...>();
};
} // namespace detail
template <auto X, auto N>
constexpr auto exponent =
detail::exponent_impl<X>(std::make_index_sequence<N>{});
```
> https://godbolt.org/z/zevEGe
```cpp
template<class T, auto N, class U>
consteval auto operator,(std::array<T, N>, U) { return std::array<U, N>{}; }
template<auto X, auto N>
constexpr auto exponent = []<auto... Ns>(std::index_sequence<Ns...>){
return sizeof((std::array<std::byte, (Ns, X)>{}, ...));
}(std::make_index_sequence<N>{});
```
> https://godbolt.org/z/Yc9nY5
</p></details>