Skip to content

Commit

Permalink
[354] - Did you know that C++23 added range string_view constructor?
Browse files Browse the repository at this point in the history
  • Loading branch information
kris-jusiak committed Oct 29, 2023
1 parent c3eedd1 commit a7fc91f
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

> C++23
* [Did you know that C++23 added range `string_view` constructor?**](https://github.com/tip-of-the-week/cpp/blob/master/tips/354.md)
* [Did you know that C++23 added `std::invoke_r`?](https://github.com/tip-of-the-week/cpp/blob/master/tips/334.md)
* [Did you know that C++23 extended floating-point types?](https://github.com/tip-of-the-week/cpp/blob/master/tips/328.md)
* [Did you know that C++23 deprecated std::aligned_storage and std::aligned_union?](https://github.com/tip-of-the-week/cpp/blob/master/tips/326.md)
Expand Down
36 changes: 36 additions & 0 deletions tips/353.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,40 @@ constexpr auto visit(auto&& f, auto&& v); // TODO
</p></details>

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

```cpp
template<class F, class V, class R, std::size_t N, std::size_t Size>
constexpr auto visit_impl([[maybe_unused]] F&& f, [[maybe_unused]] V&& v) -> R {
if constexpr (N < Size) {
switch (v.index()) {
default:
return visit_impl<F, V, R, N+1, Size>(std::forward<F>(f), std::forward<V>(v));
case N:
return std::forward<F>(f)(std::get<N>(std::forward<V>(v)));
}
} else {
__builtin_unreachable();
}
}

template<class F, class V, template<class...> class T, class... Ts>
auto result_type(T<Ts...>&&) ->
std::common_type_t<decltype(std::declval<F>()(std::get<Ts>(std::declval<V>())))...>;

template<class F, class V, template<class...> class T, class... Ts>
auto result_type(T<std::monostate, Ts...>&&) ->
std::common_type_t<decltype(std::declval<F>()(std::get<Ts>(std::declval<V>())))...>;

template<class F, class V>
constexpr decltype(auto) visit(F&& f, V&& v) {
using variant_t = std::remove_const_t<std::remove_reference_t<V>>;
constexpr auto size = std::variant_size_v<variant_t>;
static_assert(size > 0, "Empty variant is not supported!");
using result_t = decltype(result_type<F, V>(std::declval<variant_t>()));
return visit_impl<F, V, result_t, 0u, size>(std::forward<F>(f), std::forward<V>(v));
}
```
> https://godbolt.org/z/YPqGzKP95
</p></details>
36 changes: 36 additions & 0 deletions tips/354.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<details open><summary>Info</summary><p>

* **Did you know that C++23 added range `string_view` constructor?**

* https://wg21.link/P1989

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

```cpp
constexpr std::string text = "Hello, World!";
constexpr std::string_view view(text.c_str() + 7, 5);
static_assert(view == std::string_view{"World"});
```
> https://godbolt.org/z/GYfWxPc17
</p></details><details open><summary>Puzzle</summary><p>
* **Can you implement `buffer` with explicit conversion to string_view?**
```cpp
template<auto N>
struct buffer; // TODO
constexpr buffer<42> b;
static_assert(42 == std::string_view{b}.size());
static_assert(&b.data[0] == std::string_view{b}.begin());
static_assert(&b.data[42] == std::string_view{b}.end());
```

> https://godbolt.org/z/hKjo8Pr88
</p></details>

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

0 comments on commit a7fc91f

Please sign in to comment.