Skip to content

Commit 6fd094c

Browse files
authored
Merge 2021-06 LWG Motion 18
P2328R1 join_view should join all views of ranges
2 parents b549512 + 291b8d7 commit 6fd094c

File tree

1 file changed

+94
-20
lines changed

1 file changed

+94
-20
lines changed

source/ranges.tex

Lines changed: 94 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,7 @@
249249

250250
// \ref{range.join}, join view
251251
template<@\libconcept{input_range}@ V>
252-
requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>> &&
253-
(is_reference_v<range_reference_t<V>> ||
254-
@\libconcept{view}@<range_value_t<V>>)
252+
requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>>
255253
class join_view;
256254

257255
namespace views { inline constexpr @\unspec@ join = @\unspec@; }
@@ -3159,6 +3157,89 @@
31593157
\end{codeblock}
31603158
\end{itemize}
31613159

3160+
\rSec2[range.nonprop.cache]{Non-propagating cache}
3161+
3162+
\pnum
3163+
Some types in subclause \ref{range.adaptors} are specified in terms of
3164+
an exposition-only class template \exposid{non-propagating-\brk{}cache}.
3165+
\tcode{\exposid{non-propagating-cache}<T>} behaves exactly like \tcode{optional<T>}
3166+
with the following differences:
3167+
\begin{itemize}
3168+
\item
3169+
\tcode{\exposid{non-propagating-cache}<T>} constrains its type parameter \tcode{T}
3170+
with \tcode{is_object_v<T>}.
3171+
\item
3172+
The copy constructor is equivalent to:
3173+
\begin{codeblock}
3174+
constexpr @\exposid{non-propagating-cache}@(const @\exposid{non-propagating-cache}@&) noexcept { }
3175+
\end{codeblock}
3176+
\item
3177+
The move constructor is equivalent to:
3178+
\begin{codeblock}
3179+
constexpr @\exposid{non-propagating-cache}@(@\exposid{non-propagating-cache}@&& other) noexcept {
3180+
other.reset();
3181+
}
3182+
\end{codeblock}
3183+
\item
3184+
The copy assignment operator is equivalent to:
3185+
\begin{codeblock}
3186+
constexpr @\exposid{non-propagating-cache}@& operator=(const @\exposid{non-propagating-cache}@& other) noexcept {
3187+
if (addressof(other) != this)
3188+
reset();
3189+
return *this;
3190+
}
3191+
\end{codeblock}
3192+
\item
3193+
The move assignment operator is equivalent to:
3194+
\begin{codeblock}
3195+
constexpr @\exposid{non-propagating-cache}@& operator=(@\exposid{non-propagating-cache}@&& other) noexcept {
3196+
reset();
3197+
other.reset();
3198+
return *this;
3199+
}
3200+
\end{codeblock}
3201+
\item
3202+
\tcode{\exposid{non-propagating-cache}<T>} has an additional member function template
3203+
specified as follows:
3204+
\begin{itemdecl}
3205+
template<class I>
3206+
constexpr T& @\exposid{emplace-deref}@(const I& i); // \expos
3207+
\end{itemdecl}
3208+
3209+
\begin{itemdescr}
3210+
% Indenting the \item markers is necessary to avoid check errors complaining
3211+
% about missing pnum.
3212+
\mandates
3213+
The declaration \tcode{T t(*i);} is well-formed
3214+
for some invented variable \tcode{t}.
3215+
3216+
\effects
3217+
Calls \tcode{reset()}.
3218+
Then initializes the contained value as if direct-non-list-initializing
3219+
an object of type \tcode{T} with the argument \tcode{*i}.
3220+
3221+
\ensures
3222+
\tcode{*this} contains a value.
3223+
3224+
\returns
3225+
A reference to the new contained value.
3226+
3227+
\throws
3228+
Any exception thrown by the initialization of the contained value.
3229+
3230+
\remarks
3231+
If an exception is thrown during the initialization of \tcode{T},
3232+
\tcode{*this} does not contain a value, and
3233+
the previous value (if any) has been destroyed.
3234+
\end{itemdescr}
3235+
\end{itemize}
3236+
3237+
\pnum
3238+
\begin{note}
3239+
\exposid{non-propagating-cache} enables an input view
3240+
to temporarily cache values as it is iterated over.
3241+
\end{note}
3242+
31623243
\rSec2[range.all]{All view}
31633244

31643245
\rSec3[range.all.general]{General}
@@ -5066,9 +5147,7 @@
50665147
\begin{codeblock}
50675148
namespace std::ranges {
50685149
template<@\libconcept{input_range}@ V>
5069-
requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>> &&
5070-
(is_reference_v<range_reference_t<V>> ||
5071-
@\libconcept{view}@<range_value_t<V>>)
5150+
requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>>
50725151
class join_view : public view_interface<join_view<V>> {
50735152
private:
50745153
using @\exposid{InnerRng}@ = // \expos
@@ -5081,8 +5160,7 @@
50815160
struct @\exposid{sentinel}@; // \expos
50825161

50835162
V @\exposid{base_}@ = V(); // \expos
5084-
views::all_t<@\exposid{InnerRng}@> @\exposid{inner_}@ = // \expos, present only when \tcode{!is_reference_v<\exposid{InnerRng}>}
5085-
views::all_t<@\exposid{InnerRng}@>();
5163+
@\exposid{non-propagating-cache}@<remove_cv_t<@\exposid{InnerRng}@>> @\exposid{inner_}@; // \expos, present only when \tcode{!is_reference_v<\exposid{InnerRng}>}
50865164
public:
50875165
join_view() = default;
50885166
constexpr explicit join_view(V base);
@@ -5147,9 +5225,7 @@
51475225
\begin{codeblock}
51485226
namespace std::ranges {
51495227
template<@\libconcept{input_range}@ V>
5150-
requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>> &&
5151-
(is_reference_v<range_reference_t<V>> ||
5152-
@\libconcept{view}@<range_value_t<V>>)
5228+
requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>>
51535229
template<bool Const>
51545230
struct join_view<V>::@\exposid{iterator}@ {
51555231
private:
@@ -5275,15 +5351,15 @@
52755351
\effects
52765352
Equivalent to:
52775353
\begin{codeblock}
5278-
auto update_inner = [this](range_reference_t<@\exposid{Base}@> x) -> auto& {
5279-
if constexpr (@\exposid{ref-is-glvalue}@) // \tcode{x} is a reference
5280-
return x;
5354+
auto update_inner = [this](const iterator_t<@\exposid{Base}@>& x) -> auto&& {
5355+
if constexpr (@\exposid{ref-is-glvalue}@) // *x is a reference
5356+
return *x;
52815357
else
5282-
return (@\exposid{parent_}@->@\exposid{inner_}@ = views::all(std::move(x)));
5358+
return @\exposid{parent_}@->@\exposid{inner_}@.@\exposid{emplace-deref}@(x);
52835359
};
52845360

52855361
for (; @\exposid{outer_}@ != ranges::end(@\exposid{parent_}@->@\exposid{base_}@); ++@\exposid{outer_}@) {
5286-
auto& inner = update_inner(*@\exposid{outer_}@);
5362+
auto&& inner = update_inner(@\exposid{outer_}@);
52875363
@\exposid{inner_}@ = ranges::begin(inner);
52885364
if (@\exposid{inner_}@ != ranges::end(inner))
52895365
return;
@@ -5343,7 +5419,7 @@
53435419
Let \tcode{\placeholder{inner-range}} be:
53445420
\begin{itemize}
53455421
\item If \exposid{ref-is-glvalue} is \tcode{true}, \tcode{*\exposid{outer_}}.
5346-
\item Otherwise, \tcode{\exposid{parent_}->\exposid{inner_}}.
5422+
\item Otherwise, \tcode{*\exposid{parent_}->\exposid{inner_}}.
53475423
\end{itemize}
53485424

53495425
\pnum
@@ -5462,9 +5538,7 @@
54625538
\begin{codeblock}
54635539
namespace std::ranges {
54645540
template<@\libconcept{input_range}@ V>
5465-
requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>> &&
5466-
(is_reference_v<range_reference_t<V>> ||
5467-
@\libconcept{view}@<range_value_t<V>>)
5541+
requires @\libconcept{view}@<V> && @\libconcept{input_range}@<range_reference_t<V>>
54685542
template<bool Const>
54695543
struct join_view<V>::@\exposid{sentinel}@ {
54705544
private:

0 commit comments

Comments
 (0)