Skip to content

Commit

Permalink
Revert "Revert "Add views::concat_expert. views::concat with prvalue-…
Browse files Browse the repository at this point in the history
…xvalue mix disabler, expert without.""

This reverts commit fe59735.
  • Loading branch information
huixie90 committed Sep 10, 2023
1 parent dc57517 commit 265f5dd
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 23 deletions.
68 changes: 53 additions & 15 deletions concat.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ toc: true

# Revision History

## R4
- Added `views::concat_expert`.

## R3

- Redesigned `iter_swap`
Expand Down Expand Up @@ -463,12 +466,13 @@ namespace std::ranges {
// [...]

// [range.concat], concat view
template <input_range... Views>
template <bool expert_mode, input_range... Views>
requires @*see below*@
class concat_view;

namespace views {
inline constexpr @_unspecified_@ concat = @_unspecified_@;
inline constexpr @_unspecified_@ concat_expert = @_unspecified_@;
}

}
Expand Down Expand Up @@ -524,13 +528,22 @@ Add the following subclause to [range.adaptors]{.sref}.
[1]{.pnum} `concat_view` presents a `view` that concatenates all the underlying
ranges.

[2]{.pnum} The name `views::concat` denotes a customization point object
([customization.point.object]{.sref}). Given a pack of subexpressions `Es...`,
the expression `views::concat(Es...)` is expression-equivalent to
[2]{.pnum} The names `views::concat` and `views::concat_expert` denote two
customization point objects ([customization.point.object]{.sref}). Given a pack
of subexpressions `Es...`, the expression `views::concat(Es...)` is
expression-equivalent to

- [2.1]{.pnum} `views::all(Es...)` if `Es` is a pack with only one element
and `views::all(Es...)` is a well formed expression,
- [2.2]{.pnum} otherwise, `concat_view(Es...)`
- [2.2]{.pnum} otherwise, `concat_view(Es...)`, which is deduced to be the type
`concat_view<false, views::all_t<decltype(Es)>...>`.

And, the expression `views::concat_expert(Es...)` is expression-equivalent to

- [2.3]{.pnum} `views::all(Es...)` if `Es` is a pack with only one element
and `views::all(Es...)` is a well formed expression,
- [2.4]{.pnum} otherwise, `concat_view<true, views::all_t<decltype(Es)>...>(Es...)`.


\[*Example:*
```cpp
Expand Down Expand Up @@ -561,6 +574,9 @@ namespace std::ranges {
concept @*concat-indirectly-readable*@ = @*see below*@; // exposition only

template <class... Rs>
concept @*concat-require-expert*@ = @*see below*@; // exposition only

template <bool expert_mode, class... Rs>
concept @_concatable_@ = @*see below*@; // exposition only

template <bool Const, class... Rs>
Expand All @@ -574,10 +590,10 @@ namespace std::ranges {
template <bool Const, class... Rs>
concept @_concat-is-bidirectional_@ = @*see below*@; // exposition only

template <input_range... Views>
template <bool expert_mode, input_range... Views>
requires (view<Views> && ...) && (sizeof...(Views) > 0) &&
@_concatable_@<Views...>
class concat_view : public view_interface<concat_view<Views...>> {
@_concatable_@<expert_mode, Views...>
class concat_view : public view_interface<concat_view<expert_mode, Views...>> {
tuple<Views...> @*views_*@; // exposition only

template <bool Const>
Expand All @@ -603,7 +619,7 @@ namespace std::ranges {
};

template <class... R>
concat_view(R&&...) -> concat_view<views::all_t<R>...>;
concat_view(R&&...) -> concat_view<false, views::all_t<R>...>;
}
```
Expand Down Expand Up @@ -640,8 +656,29 @@ concept @*concat-indirectly-readable*@ = // exposition only
:::
```cpp
template <class... Rs>
concept @*concat-require-expert*@ = @*see below*@; // exposition only
```

:::bq

[2]{.pnum} The exposition-only `@*concat-require-expert*@` concept is equivalent to:

```cpp
template <class... Rs>
concept @*concat-require-expert*@ = // exposition only
is_reference_v<@*concat-reference-t*@<Rs...>> ||
((!is_reference_v<range_reference_t<Rs>> ||
!same_as<remove_reference_t<range_reference_t<Rs>>, @*concat-reference-t*@<Rs...>>)
&& ...);
```
:::
```cpp
template <bool expert_mode, class... Rs>
concept @_concatable_@ = @*see below*@; // exposition only
```

Expand All @@ -651,12 +688,13 @@ concept @_concatable_@ = @*see below*@; // exposition only
concept is equivalent to:

```cpp
template <class... Rs>
template <bool expert_mode, class... Rs>
concept @_concatable_@ = requires { // exposition only
typename @*concat-reference-t*@<Rs...>;
typename @*concat-value-t*@<Rs...>;
typename @*concat-rvalue-reference-t*@<Rs...>;
} && @*concat-indirectly-readable*@<Rs...>;
} && @*concat-indirectly-readable*@<Rs...>
&& (expert_mode || @*concat-require-expert*@<Rs...>);
```
:::
Expand Down Expand Up @@ -709,7 +747,7 @@ constexpr explicit concat_view(Views... views);
```cpp
constexpr @_iterator_@<false> begin() requires(!(@_simple-view_@<Views> && ...));
constexpr @_iterator_@<true> begin() const
requires((range<const Views> && ...) && @_concatable_@<const Views...>);
requires((range<const Views> && ...) && @_concatable_@<expert_mode, const Views...>);
```
:::bq
Expand Down Expand Up @@ -774,11 +812,11 @@ return apply(
```cpp
namespace std::ranges{

template <input_range... Views>
template <bool expert_mode, input_range... Views>
requires (view<Views> && ...) && (sizeof...(Views) > 0) &&
@_concatable_@<Views...>
@_concatable_@<expert_mode, Views...>
template <bool Const>
class concat_view<Views...>::@_iterator_@ {
class concat_view<expert_mode, Views...>::@_iterator_@ {

public:
using iterator_category = @*see below*@; // not always present.
Expand Down
41 changes: 33 additions & 8 deletions impl/concat/concat.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ using concat_rvalue_reference_t =
template <class... Rs>
using concat_value_t = common_type_t<range_value_t<Rs>...>;

// modelled only if concat reference_t is a prvalue T and at least one of the
// argument ranges' reference_t is a T reference
template <class... Rs>
concept concat_require_expert =
is_reference_v<concat_reference_t<Rs...>> ||
(is_reference_v<range_reference_t<Rs>>&&...) &&
(!same_as<std::remove_reference_t<range_reference_t<Rs>>,
concat_reference_t<Rs...>> &&
...);

// clang-format off
template <class Ref, class RRef, class It>
concept concat_indirectly_readable_impl = requires (const It it){
Expand All @@ -55,12 +65,14 @@ concept concat_indirectly_readable =
} // namespace not_to_spec

// clang-format off
template <class... Rs>
template <bool expert_mode, class... Rs>
concept concatable = requires {
typename concat_reference_t<Rs...>;
typename concat_value_t<Rs...>;
typename concat_rvalue_reference_t<Rs...>;
} && concat_indirectly_readable<Rs...>;
} && concat_indirectly_readable<Rs...>
&& (expert_mode || concat_require_expert<Rs...>)
;
// clang-format on

static_assert(true); // clang-format badness
Expand Down Expand Up @@ -246,9 +258,9 @@ using iter_cat_base_t = decltype(iter_cat_base_sel<Const, Views...>());

// clang-format off
// [TODO] constrain less and allow just a `view`? (i.e. including output_range in the mix - need an example)
template <input_range... Views>
requires (view<Views>&&...) && (sizeof...(Views) > 0) && xo::concatable<Views...>
class concat_view : public view_interface<concat_view<Views...>> {
template <bool expert_mode, input_range... Views>
requires (view<Views>&&...) && (sizeof...(Views) > 0) && xo::concatable<expert_mode, Views...>
class concat_view : public view_interface<concat_view<expert_mode, Views...>> {
// clang-format on
tuple<Views...> views_; // exposition only

Expand Down Expand Up @@ -627,7 +639,7 @@ class concat_view : public view_interface<concat_view<Views...>> {

constexpr iterator<true> begin() const
requires((range<const Views> && ...) &&
xo::concatable<const Views...>) //
xo::concatable<expert_mode, const Views...>) //
{
iterator<true> it(this, in_place_index<0u>, ranges::begin(get<0>(views_)));
it.template satisfy<0>();
Expand Down Expand Up @@ -676,7 +688,7 @@ class concat_view : public view_interface<concat_view<Views...>> {
};

template <class... R>
concat_view(R&&...) -> concat_view<views::all_t<R>...>;
concat_view(R&&...) -> concat_view<false, views::all_t<R>...>;

// cpo:

Expand All @@ -693,17 +705,30 @@ class concat_fn {
}

template <input_range... V>
requires(sizeof...(V) > 1) && ranges::xo::concatable<all_t<V&&>...> &&
requires(sizeof...(V) > 1) && ranges::xo::concatable<false, all_t<V&&>...> &&
(viewable_range<V> && ...) //
constexpr auto
operator()(V&&... v)
const { // noexcept(noexcept(concat_view{static_cast<V&&>(v)...})) {
return concat_view{static_cast<V&&>(v)...};
}
};

class concat_expert_fn : concat_fn {
public:
template <input_range... V>
requires(sizeof...(V) > 1) && ranges::xo::concatable<true, all_t<V&&>...> &&
(viewable_range<V> && ...) //
constexpr auto
operator()(V&&... v)
const { // noexcept(noexcept(concat_view{static_cast<V&&>(v)...})) {
return concat_view<true, views::all_t<V>...>{static_cast<V&&>(v)...};
}
};
} // namespace xo

inline constexpr xo::concat_fn concat;
inline constexpr xo::concat_expert_fn concat_expert;
} // namespace views

} // namespace std::ranges
Expand Down

0 comments on commit 265f5dd

Please sign in to comment.