|
249 | 249 |
|
250 | 250 | // \ref{range.join}, join view
|
251 | 251 | 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>> |
255 | 253 | class join_view;
|
256 | 254 |
|
257 | 255 | namespace views { inline constexpr @\unspec@ join = @\unspec@; }
|
|
3159 | 3157 | \end{codeblock}
|
3160 | 3158 | \end{itemize}
|
3161 | 3159 |
|
| 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 | + |
3162 | 3243 | \rSec2[range.all]{All view}
|
3163 | 3244 |
|
3164 | 3245 | \rSec3[range.all.general]{General}
|
|
5066 | 5147 | \begin{codeblock}
|
5067 | 5148 | namespace std::ranges {
|
5068 | 5149 | 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>> |
5072 | 5151 | class join_view : public view_interface<join_view<V>> {
|
5073 | 5152 | private:
|
5074 | 5153 | using @\exposid{InnerRng}@ = // \expos
|
|
5081 | 5160 | struct @\exposid{sentinel}@; // \expos
|
5082 | 5161 |
|
5083 | 5162 | 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}>} |
5086 | 5164 | public:
|
5087 | 5165 | join_view() = default;
|
5088 | 5166 | constexpr explicit join_view(V base);
|
|
5147 | 5225 | \begin{codeblock}
|
5148 | 5226 | namespace std::ranges {
|
5149 | 5227 | 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>> |
5153 | 5229 | template<bool Const>
|
5154 | 5230 | struct join_view<V>::@\exposid{iterator}@ {
|
5155 | 5231 | private:
|
|
5275 | 5351 | \effects
|
5276 | 5352 | Equivalent to:
|
5277 | 5353 | \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; |
5281 | 5357 | else
|
5282 |
| - return (@\exposid{parent_}@->@\exposid{inner_}@ = views::all(std::move(x))); |
| 5358 | + return @\exposid{parent_}@->@\exposid{inner_}@.@\exposid{emplace-deref}@(x); |
5283 | 5359 | };
|
5284 | 5360 |
|
5285 | 5361 | 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_}@); |
5287 | 5363 | @\exposid{inner_}@ = ranges::begin(inner);
|
5288 | 5364 | if (@\exposid{inner_}@ != ranges::end(inner))
|
5289 | 5365 | return;
|
|
5343 | 5419 | Let \tcode{\placeholder{inner-range}} be:
|
5344 | 5420 | \begin{itemize}
|
5345 | 5421 | \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_}}. |
5347 | 5423 | \end{itemize}
|
5348 | 5424 |
|
5349 | 5425 | \pnum
|
|
5462 | 5538 | \begin{codeblock}
|
5463 | 5539 | namespace std::ranges {
|
5464 | 5540 | 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>> |
5468 | 5542 | template<bool Const>
|
5469 | 5543 | struct join_view<V>::@\exposid{sentinel}@ {
|
5470 | 5544 | private:
|
|
0 commit comments