Skip to content

Commit

Permalink
order fixup
Browse files Browse the repository at this point in the history
  • Loading branch information
kris-jusiak committed Aug 13, 2023
1 parent 7391297 commit c4b4f33
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 171 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
* [[342]](https://github.com/QuantlabFinancial/cpp_tip_of_the_week/blob/master/tips/342.md) - Did you know that C++26 added 'A nice placeholder with no name'?
* [[341]](https://github.com/QuantlabFinancial/cpp_tip_of_the_week/blob/master/tips/341.md) - Did you know that C++26 added user-generated static_assert messages?
* [[340]](https://github.com/QuantlabFinancial/cpp_tip_of_the_week/blob/master/tips/340.md) - Did you know that C++26 added bind front and back to NTTP callables?
* [[339]](https://github.com/QuantlabFinancial/cpp_tip_of_the_week/blob/master/tips/339.md) - Did you know about C++20 `std::next_permutation` algorithm?
* [[338]](https://github.com/QuantlabFinancial/cpp_tip_of_the_week/blob/master/tips/338.md) - Did you know that C++26 added `@, $, and `` to the basic character set?
* [[339]](https://github.com/QuantlabFinancial/cpp_tip_of_the_week/blob/master/tips/339.md) - Did you know that C++26 added `@, $, and `` to the basic character set?
* [[338]](https://github.com/QuantlabFinancial/cpp_tip_of_the_week/blob/master/tips/338.md) - Did you know about C++20 `std::next_permutation` algorithm?
* [[337]](https://github.com/QuantlabFinancial/cpp_tip_of_the_week/blob/master/tips/337.md) - Did you know that run-time dispatching over type-list can be implemented many different ways?
* [[336]](https://github.com/QuantlabFinancial/cpp_tip_of_the_week/blob/master/tips/336.md) - Did you know about `gnu::vector_size` extension?
* [[335]](https://github.com/QuantlabFinancial/cpp_tip_of_the_week/blob/master/tips/335.md) - Did you know that you can simplify `boost.mp11` API with DSL?
Expand Down
169 changes: 156 additions & 13 deletions tips/338.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,176 @@
<details open><summary>Info</summary><p>

* **Did you know that C++26 added `@, $, and `` to the basic character set?**
* **Did you know about C++20 `std::next_permutation` algorithm?**

* https://wg21.link/P2558R2
* https://eel.is/c++draft/alg.permutation.generators#lib:next_permutation

</p></details><details open><summary>Example</summary><p>

```cpp
auto $dollar_sign = 42;
auto @commerical_at = 42;
auto `grave_accent = 42;
[[nodiscard]] constexpr auto factorial(const auto n) {
if (n == 0 or n == 1) {
return 1;
}
auto result = 1;
for (auto i = 2; i <= n; ++i) {
result *= i;
}
return result;
}
static_assert(1 == factorial(0));
static_assert(1 == factorial(1));
static_assert(1 * 2 == factorial(2));
static_assert(1 * 2 * 3 == factorial(3));
static_assert(1 * 2 * 3 * 4 == factorial(4));
static_assert(1 * 2 * 3 * 4 * 5 == factorial(5));
static_assert(1 * 2 * 3 * 4 * 5 * 6 == factorial(6));
```
> https://godbolt.org/z/14r8EdevM
</p></details><details open><summary>Puzzle</summary><p>
* **Can you write code snippets where added characters can be used with added value?**
* **Can you implement `permute invoke` which will try to call using all possible permutations?**
```cpp
// TODO invoke
template <auto>
struct Foo {};
constexpr auto foo() { return 1; }
constexpr auto bar(Foo<0>) { return 2; } constexpr auto baz(Foo<0>, Foo<1>) { return 3; }
static_assert(1 == invoke<int>(foo));
static_assert(2 == invoke<int>(bar, Foo<0>{}));
static_assert(3 == invoke<int>(baz, Foo<0>{}, Foo<1>{}));
static_assert(3 == invoke<int>(baz, Foo<1>{}, Foo<0>{}));
```

> https://godbolt.org/z/xeaxP46qW
</p></details><details><summary>Solutions</summary><p>

```cpp
// math
auto a = 42;
auto a` = a*2;
template <class T, auto N>
[[nodiscard]] constexpr auto permute(std::array<T, N> nums) {
std::array<std::array<T, N>, factorial(N)> result{};
auto i = 0;
do {
result[i++] = nums;
} while (std::next_permutation(nums.begin(), nums.end()));
return result;
}

namespace detail {
template<class> constexpr auto invoke(auto fn, auto... ts) -> std::pair<bool, decltype(fn(ts...))> { return {true, fn(ts...)}; }
template<class R> constexpr auto invoke(...) -> std::pair<bool, R> { return {false, {}}; }

template<auto N> constexpr auto nth(auto... args) {
return [&]<auto... Ns>(std::index_sequence<Ns...>) {
return [](decltype((void*)Ns)..., auto* nth, auto*...) {
return *nth;
}(&args...);
}
(std::make_index_sequence<N>{});
}
} // namespace detail

template<class R>
constexpr auto invoke(auto fn, auto... ts) -> R {
constexpr auto ids = []<auto... Ns>(std::index_sequence<Ns...>) { return std::array<std::size_t, sizeof...(Ns)>{Ns...}; }(std::make_index_sequence<sizeof...(ts)>{});
constexpr auto permutations = permute(ids);

R result;
bool called{};
[&]<auto... Ns>(std::index_sequence<Ns...>) {
([&]<auto N, auto... Is>(std::index_sequence<Is...>) {
std::tie(called, result) = detail::invoke<R>(fn, detail::nth<permutations[N][Is]>(ts...)...);
return called;
}.template operator()<Ns>(std::make_index_sequence<permutations[Ns].size()>{}) or ...);
}(std::make_index_sequence<permutations.size()>{});
return result;
}
```
> https://godbolt.org/z/vKbofePes
```cpp
template <class T, auto N>
[[nodiscard]] constexpr auto permute(std::array<T, N> nums) {
std::array<std::array<T, N>, factorial(N)> result{};
auto i = 0;
do {
result[i++] = nums;
} while (std::next_permutation(nums.begin(), nums.end()));
return result;
}
namespace detail {
template<class, auto N> constexpr auto invoke(auto fn, auto... ts) -> std::pair<std::integral_constant<int, N>, decltype(fn(ts...))> { return {{}, fn(ts...)}; }
template<class R, auto> constexpr auto invoke(...) -> std::pair<std::integral_constant<int, 0>, R> { return {}; }
// macros
$macro(...) ```
template<auto N> constexpr auto nth(auto... args) {
return [&]<auto... Ns>(std::index_sequence<Ns...>) {
return [](decltype((void*)Ns)..., auto* nth, auto*...) {
return *nth;
}(&args...);
}
(std::make_index_sequence<N>{});
}
// twitter
auto id = @krisjusiak;
template<class R, auto I, auto Size, auto Permutations, auto Split>
constexpr auto invoke_impl(auto fn, auto... ts) -> R {
if constexpr (I >= Size) {
return {};
} else {
constexpr auto N = [&]<auto... Ns>(std::index_sequence<Ns...>) {
return ([&]<auto N, auto... Is>(std::index_sequence<Is...>) {
return decltype(detail::invoke<R, N+1>(fn, detail::nth<Permutations[N][Is]>(ts...)...)){}.first.value;
}.template operator()<I+Ns>(std::make_index_sequence<Permutations[I+Ns].size()>{}) + ...);
}(std::make_index_sequence<Split>{});
if constexpr (N > 0) {
constexpr auto N_ = N - 1;
return [&]<auto... Is>(std::index_sequence<Is...>) {
return detail::invoke<R, N_>(fn, detail::nth<Permutations[N_][Is]>(ts...)...).second;
}(std::make_index_sequence<Permutations[N_].size()>{});
} else {
constexpr auto chunks = Size / Split;
return invoke_impl<R, I+chunks, chunks, Permutations>(fn, ts...);
}
}
}
} // namespace detail
template<class R>
constexpr auto invoke(auto fn, auto... ts) -> R {
constexpr auto ids = []<auto... Ns>(std::index_sequence<Ns...>) { return std::array<std::size_t, sizeof...(Ns)>{Ns...}; }(std::make_index_sequence<sizeof...(ts)>{});
constexpr auto permutations = permute(ids);
constexpr auto max_params_without_chunking = 7;
constexpr auto split = 10;
if constexpr (sizeof...(ts) < max_params_without_chunking) {
constexpr auto N = [&]<auto... Ns>(std::index_sequence<Ns...>) {
return ([&]<auto N, auto... Is>(std::index_sequence<Is...>) {
return decltype(detail::invoke<R, N+1>(fn, detail::nth<permutations[N][Is]>(ts...)...)){}.first.value;
}.template operator()<Ns>(std::make_index_sequence<permutations[Ns].size()>{}) + ...);
}(std::make_index_sequence<permutations.size()>{});
if constexpr (N > 0) {
constexpr auto N_ = N - 1;
return [&]<auto... Is>(std::index_sequence<Is...>) {
return detail::invoke<R, N_>(fn, detail::nth<permutations[N_][Is]>(ts...)...).second;
}(std::make_index_sequence<permutations[N_].size()>{});
} else {
return {};
}
} else {
return detail::invoke_impl<R, 0, permutations.size(), permutations, split>(fn, ts...);
}
}
```

> https://godbolt.org/z/97ejzW4Px
</p></details>
169 changes: 13 additions & 156 deletions tips/339.md
Original file line number Diff line number Diff line change
@@ -1,176 +1,33 @@
<details open><summary>Info</summary><p>

* **Did you know about C++20 `std::next_permutation` algorithm?**
* **Did you know that C++26 added `@, $, and `` to the basic character set?**

* https://eel.is/c++draft/alg.permutation.generators#lib:next_permutation
* https://wg21.link/P2558R2

</p></details><details open><summary>Example</summary><p>

```cpp
[[nodiscard]] constexpr auto factorial(const auto n) {
if (n == 0 or n == 1) {
return 1;
}
auto result = 1;
for (auto i = 2; i <= n; ++i) {
result *= i;
}
return result;
}
static_assert(1 == factorial(0));
static_assert(1 == factorial(1));
static_assert(1 * 2 == factorial(2));
static_assert(1 * 2 * 3 == factorial(3));
static_assert(1 * 2 * 3 * 4 == factorial(4));
static_assert(1 * 2 * 3 * 4 * 5 == factorial(5));
static_assert(1 * 2 * 3 * 4 * 5 * 6 == factorial(6));
auto $dollar_sign = 42;
auto @commerical_at = 42;
auto `grave_accent = 42;
```

> https://godbolt.org/z/14r8EdevM
</p></details><details open><summary>Puzzle</summary><p>

* **Can you implement `permute invoke` which will try to call using all possible permutations?**
```cpp
// TODO invoke
template <auto>
struct Foo {};
constexpr auto foo() { return 1; }
constexpr auto bar(Foo<0>) { return 2; } constexpr auto baz(Foo<0>, Foo<1>) { return 3; }
static_assert(1 == invoke<int>(foo));
static_assert(2 == invoke<int>(bar, Foo<0>{}));
static_assert(3 == invoke<int>(baz, Foo<0>{}, Foo<1>{}));
static_assert(3 == invoke<int>(baz, Foo<1>{}, Foo<0>{}));
```

> https://godbolt.org/z/xeaxP46qW
* **Can you write code snippets where added characters can be used with added value?**

</p></details><details><summary>Solutions</summary><p>

```cpp
template <class T, auto N>
[[nodiscard]] constexpr auto permute(std::array<T, N> nums) {
std::array<std::array<T, N>, factorial(N)> result{};
auto i = 0;
do {
result[i++] = nums;
} while (std::next_permutation(nums.begin(), nums.end()));
return result;
}

namespace detail {
template<class> constexpr auto invoke(auto fn, auto... ts) -> std::pair<bool, decltype(fn(ts...))> { return {true, fn(ts...)}; }
template<class R> constexpr auto invoke(...) -> std::pair<bool, R> { return {false, {}}; }

template<auto N> constexpr auto nth(auto... args) {
return [&]<auto... Ns>(std::index_sequence<Ns...>) {
return [](decltype((void*)Ns)..., auto* nth, auto*...) {
return *nth;
}(&args...);
}
(std::make_index_sequence<N>{});
}
} // namespace detail

template<class R>
constexpr auto invoke(auto fn, auto... ts) -> R {
constexpr auto ids = []<auto... Ns>(std::index_sequence<Ns...>) { return std::array<std::size_t, sizeof...(Ns)>{Ns...}; }(std::make_index_sequence<sizeof...(ts)>{});
constexpr auto permutations = permute(ids);

R result;
bool called{};
[&]<auto... Ns>(std::index_sequence<Ns...>) {
([&]<auto N, auto... Is>(std::index_sequence<Is...>) {
std::tie(called, result) = detail::invoke<R>(fn, detail::nth<permutations[N][Is]>(ts...)...);
return called;
}.template operator()<Ns>(std::make_index_sequence<permutations[Ns].size()>{}) or ...);
}(std::make_index_sequence<permutations.size()>{});
return result;
}
```
> https://godbolt.org/z/vKbofePes
```cpp
template <class T, auto N>
[[nodiscard]] constexpr auto permute(std::array<T, N> nums) {
std::array<std::array<T, N>, factorial(N)> result{};
auto i = 0;
do {
result[i++] = nums;
} while (std::next_permutation(nums.begin(), nums.end()));
return result;
}
namespace detail {
template<class, auto N> constexpr auto invoke(auto fn, auto... ts) -> std::pair<std::integral_constant<int, N>, decltype(fn(ts...))> { return {{}, fn(ts...)}; }
template<class R, auto> constexpr auto invoke(...) -> std::pair<std::integral_constant<int, 0>, R> { return {}; }
// math
auto a = 42;
auto a` = a*2;

template<auto N> constexpr auto nth(auto... args) {
return [&]<auto... Ns>(std::index_sequence<Ns...>) {
return [](decltype((void*)Ns)..., auto* nth, auto*...) {
return *nth;
}(&args...);
}
(std::make_index_sequence<N>{});
}
// macros
$macro(...) ```

template<class R, auto I, auto Size, auto Permutations, auto Split>
constexpr auto invoke_impl(auto fn, auto... ts) -> R {
if constexpr (I >= Size) {
return {};
} else {
constexpr auto N = [&]<auto... Ns>(std::index_sequence<Ns...>) {
return ([&]<auto N, auto... Is>(std::index_sequence<Is...>) {
return decltype(detail::invoke<R, N+1>(fn, detail::nth<Permutations[N][Is]>(ts...)...)){}.first.value;
}.template operator()<I+Ns>(std::make_index_sequence<Permutations[I+Ns].size()>{}) + ...);
}(std::make_index_sequence<Split>{});
if constexpr (N > 0) {
constexpr auto N_ = N - 1;
return [&]<auto... Is>(std::index_sequence<Is...>) {
return detail::invoke<R, N_>(fn, detail::nth<Permutations[N_][Is]>(ts...)...).second;
}(std::make_index_sequence<Permutations[N_].size()>{});
} else {
constexpr auto chunks = Size / Split;
return invoke_impl<R, I+chunks, chunks, Permutations>(fn, ts...);
}
}
}
} // namespace detail
template<class R>
constexpr auto invoke(auto fn, auto... ts) -> R {
constexpr auto ids = []<auto... Ns>(std::index_sequence<Ns...>) { return std::array<std::size_t, sizeof...(Ns)>{Ns...}; }(std::make_index_sequence<sizeof...(ts)>{});
constexpr auto permutations = permute(ids);
constexpr auto max_params_without_chunking = 7;
constexpr auto split = 10;
if constexpr (sizeof...(ts) < max_params_without_chunking) {
constexpr auto N = [&]<auto... Ns>(std::index_sequence<Ns...>) {
return ([&]<auto N, auto... Is>(std::index_sequence<Is...>) {
return decltype(detail::invoke<R, N+1>(fn, detail::nth<permutations[N][Is]>(ts...)...)){}.first.value;
}.template operator()<Ns>(std::make_index_sequence<permutations[Ns].size()>{}) + ...);
}(std::make_index_sequence<permutations.size()>{});
if constexpr (N > 0) {
constexpr auto N_ = N - 1;
return [&]<auto... Is>(std::index_sequence<Is...>) {
return detail::invoke<R, N_>(fn, detail::nth<permutations[N_][Is]>(ts...)...).second;
}(std::make_index_sequence<permutations[N_].size()>{});
} else {
return {};
}
} else {
return detail::invoke_impl<R, 0, permutations.size(), permutations, split>(fn, ts...);
}
}
// twitter
auto id = @krisjusiak;
```

> https://godbolt.org/z/97ejzW4Px
</p></details>

0 comments on commit c4b4f33

Please sign in to comment.