From 706d1a71f9b85a1e8da76fe7db99f080655b1a5d Mon Sep 17 00:00:00 2001 From: Hui Date: Mon, 5 Jun 2023 21:40:39 +0100 Subject: [PATCH] more fix to the concat wording --- concat.lwg.feedback.md | 412 ++++++++++++++++++++++------------------- concat.md | 106 +++++------ impl/concat/concat.hpp | 6 +- 3 files changed, 272 insertions(+), 252 deletions(-) diff --git a/concat.lwg.feedback.md b/concat.lwg.feedback.md index ba5236f..653bfed 100644 --- a/concat.lwg.feedback.md +++ b/concat.lwg.feedback.md @@ -1,201 +1,227 @@ # Done -[Done] 5.2 needs to go -[Done] we don't need 24.7.?.1 p2.3 and strick "if this expression is well formed" from 2.2 -[Done] in 24.7.?.2 add exposition-only for these concepts -[Done] we need to require the entire expression to be equality preserving: we could add CC's code -[Done] on p3 the pack needs to be expanded as I put into the chat -[Done] remove the requires from the default constructor an remove the initialization of views_ -[Done] in the size the make_unsigned_t should be make_unsigned_like_t as it could be integer-like -[Done] on size() the {} need to be () -[Done] also CT(0) isn't needed - the sequence is always non-empty -[Done] value_type could use concat_value_t -[Done] we don't need the friends -[Done] the requires on the default ctor isn't needed -[Done] and remove initialization from base-iter() -[Done] op-- is missing a ; -[Done] there is iterator const& which should be const iterator& (this is editorial) -[Done] 2.1 should say is_reference_v -[Done] all the other bullets need to start with "otherwise" -[Done] you should use ranges::distance and then you don't need them -[Done] instead of ranges::size this should be ranges::distance and we don't need the static_cast. -[Done] all the steps need to cast to that iterator's difference_type -[Done] al the steps need to be cast to range::diffence_type -[Done] the use of maybe-const on the requirement of the constructor: I think we removed them elsewhere as we Const is true +- [Done] 5.2 needs to go +- [Done] we don't need 24.7.?.1 p2.3 and strick "if this expression is well formed" from 2.2 +- [Done] in 24.7.?.2 add exposition-only for these concepts +- [Done] we need to require the entire expression to be equality preserving: we could add CC's code +- [Done] on p3 the pack needs to be expanded as I put into the chat +- [Done] remove the requires from the default constructor an remove the initialization of views_ +- [Done] in the size the make_unsigned_t should be make_unsigned_like_t as it could be integer-like +- [Done] on size() the {} need to be () +- [Done] also CT(0) isn't needed - the sequence is always non-empty +- [Done] value_type could use concat_value_t +- [Done] we don't need the friends +- [Done] the requires on the default ctor isn't needed +- [Done] and remove initialization from base-iter() +- [Done] op-- is missing a ; +- [Done] there is iterator const& which should be const iterator& (this is editorial) +- [Done] 2.1 should say is_reference_v +- [Done] all the other bullets need to start with "otherwise" +- [Done] you should use ranges::distance and then you don't need them +- [Done] instead of ranges::size this should be ranges::distance and we don't need the static_cast. +- [Done] all the steps need to cast to that iterator's difference_type +- [Done] al the steps need to be cast to range::diffence_type +- [Done] the use of maybe-const on the requirement of the constructor: I think we removed them elsewhere as we Const is true +- [Done] OK, we can keep it as is but I prefer < +- [Done] for op*() p10 can use concat_reference_t +- [Done] we don't need the preconditions: they come from the "Equivalent to:" => strike p13 and p15 +- [Done] you need p17 but you can rid of p19 +- [Done] we should spell out what reference is in 2.1 # Todos -[TODO] mattermost: CC: we should ask the aurthors to remove the section numbers -[TODO] mattermost: TZ/CC: wording the concat-bidirectional - -[TODO] when doing zip_view and cartesian_product we added maybe_const so we don't need to do that everywhere and we should do that here, too -[TODO] that "expect" needs to be "except" -[TODO] for the op++ and the others we should use the random-access from zip_view -[TODO] the concepts from zip_view [rang.zip.iterator] need to move to a different section: move to [range.utility.helper] -[TODO] the things which use the general concepts are replaced: op++, op<, etc. -[TODO] (1.3) use all_forward -[TODO] OK, we can keep it as is but I prefer < -[TODO] do we want to avoid emplacing ranges we don't need to use? -[TODO] explain why this is over-constrained -[TODO] for op*() p10 can use concat_reference_t -[TODO] we don't need the preconditions: they come from the "Equivalent to:" => strike p13 and p15 -[TODO] you need p17 but you can rid of p19 -[TODO] we should spell out what reference is in 2.1 -[TODO] put the front matter after the iterator_category -[TODO] we should use a single definition for the relational operators similar to basic_const_iterator [const.iterator.ops] p19 -[TODO] I think the authors need to think about iter_swap and provide rational +- [TODO] mattermost: CC: we should ask the aurthors to remove the section numbers + - Hui: Do you know what section numbers Casey refers to? + +- [TODO] mattermost: TZ/CC: wording the concat-bidirectional + - Hui: From the chat history they don't seem to be happy about our wording and had some alternative wordings in the chat + +- [TODO] when doing zip_view and cartesian_product we added maybe_const so we don't need to do that everywhere and we should do that here, too + - Hui: ? + +- [TODO] that "expect" needs to be "except" + - Hui: could not find any expect + +- [TODO] for the op++ and the others we should use the random-access from zip_view + - Hui: zip_view's op++ requires all-random-access but we need random_access + sized + +- [TODO] the concepts from zip_view [rang.zip.iterator] need to move to a different section: move to [range.utility.helper] + - Hui: I think they refer to all-random-access, all-bidirectional and all-forward. In practice, we can only use all-forward. Not sure if it is worth + +- [TODO] the things which use the general concepts are replaced: op++, op<, etc. + - Hui: Not sure if I understand this. I guess they could either mean + - 1. we could replace `random_access_range>&&...` with `all-random-access`, or + - 2. some of our ops requires `concat-random-access` but others requires `random_access_range>&&...`. We should be consistent? + +- [TODO] (1.3) use all_forward + - Hui: We could. but it seems to be more effort to reuse this simple concepts than it saves. what do you think? + +- [TODO] do we want to avoid emplacing ranges we don't need to use? + - Hui: Good point. I think this refers to `advance_fwd` and `advance_bwd`. Maybe we can do something smarter. + +- [TODO] explain why this is over-constrained + - Hui: Not sure what this refers to + +- [TODO] put the front matter after the iterator_category + - Hui: I think this refers to all the preconditions about variant's valueless state. It is good idea but I don't know how to do it. I mean, how to specify what operations are allowed and what are not. Need prio examples. + +- [TODO] we should use a single definition for the relational operators similar to basic_const_iterator [const.iterator.ops] p19 + - Hui: I just learned we can specify that way. Not sure if you like it? + +- [TODO] I think the authors need to think about iter_swap and provide rational + - Hui: sg9? # Full transcript -JG: this is for C++26 -JG presenting -TK: do we still use tie? -TS: this paper doesn't actually use tuple or pair -TS: 5.2 is already done -JG: this came in with zip or so. -TS: [action] 5.2 needs to go -TK: what about concat of no views? -JG: don't do that -TS: ill-formed -CC: [action] we don't need 24.7.?.1 p2.3 and strick "if this expression is well formed" from 2.2 -TK: do we want to allow concat_view of one view -RD: the pre-matter does talk about 0 and 1 view and it is all_view -TK: but I can still use concat_view explicitly with 1 object -TS: that doesn't seem justified: you can get a take_view of a string_view and get a string_view back -TK: do we have common_reference_t with single argument? -TS: I'm pretty sure we do: we can have it with any number of argument > 0 -TS: we should change the example to use print instead of cout -JG: is there something special about concat-random-access which we don't have under some other concept? -CC: in general these concepts are models requirements and are needed when implementing the view -TK: [action] when doing zip_view and cartesian_product we added maybe_const so we don't need to do that everywhere and we should do that here, too -RD: do we have a recommended way to word the concepts like the concept-indriectly-readable -RD: how consistent do we want these wordings to be be? -RD: the approach used here is otherwise only by iota_view -RD: there is "exposition-only" repeated for iota_view -JG: [action] in 24.7.?.2 add exposition-only for these concepts -JG: we tend to remove the section names -TS: the concept uses static_cast - where do we require the implicit conversion work? -TK: we required common_refernce_t but not common_reference_with -CC: this is the impl-version; the other requires common_reference_with -TS: we require each of the iterator types to have something convertible_to but I don't see we check that -JG: so we have a required change -TS: it should require convertible_to in addition to the two expressions -TS: if you do things multiple times you end up getting totally nonsensical result -TK: do you mean implicate conversions? -CC: do we change to the requires expression to what I typed in the chat? -TS: [action] we need to require the entire expression to be equality preserving: we could add CC's code -TK: I have another variation how to spell that in the chat -TS: we can do that, too - I don't mind how we spell it -TK: I believe it is the same thing -RD: [action] on p3 the pack needs to be expanded as I put into the chat -TS: the types model a concept; this one is ugly -TS: it needs to say both satisfies and models -JG: why the requirement on 3.2? -CC: we should add a "The" at the begining of 3.1 -CC: [action] that "expect" needs to be "except" -TS: I'd like to say this in code instead of word - or pseudo code -JG: TS's homework is to put suggested wording into the chat or send it to the author -TK: for the end: the last element is always the last element of the pack and then we can apply constness when needed (see chat) -TS: on the concept view: we don't need the default_initializable -JG: [action] remove the requires from the default constructor an remove the initialization of views_ -TK: [action] in the size the make_unsigned_t should be make_unsigned_like_t as it could be integer-like -RD: the as_const stuff is just missing an article in multiple places -CC: [action] on size() the {} need to be () -TS: [action] also CT(0) isn't needed - the sequence is always non-empty -TK: [action] value_type could use concat_value_t -TS: the maybe-const needs to be there -JG: unless we restructure as TK has mentioned -TK: [action] we don't need the friends -JG: do we need the = base-iter();? -TK: it is a variant: it will construct the first element -TK: [action] the requires on the default ctor isn't needed -TK: [action] and remove initialization from base-iter() -TS: it is weird that the default is tied to the first iterator in the range specifically -DK: the default ctor doesn't mean anything -TS: yes, it can only be compared to itself -DK: so we could have a special variant member -TS: it could use monostate instead of depending on the first iterator -TS: I would add monostate to the end and initialize with that -TK: but why at the end? -TS: I think it is nicer at the end if we add monostate -TK: I'd be more comfortable that it is default constructible if any iterator is default constructable -TS: that is harder to implement; it is simple to add monostate and always use that -TS: but then everything visiting the variant is harder - so I take that back: I think I can accept the weirdness -RD: [action] op-- is missing a ; -TK: [action] for the op++ and the others we should use the random-access from zip_view -TS: [action] the concepts from zip_view [rang.zip.iterator] need to move to a different section: move to [range.utility.helper] -TS: maybe we should promote [range.utility.helper] to something higher -CC: seems odd that we have compile-time and run-time range helper; this is a change which can be done outside this paper -TK: all the relational operators should use the random-access -JG: [action] the things which use the general concepts are replaced: op++, op<, etc. -CC: [action] there is iterator const& which should be const iterator& (this is editorial) -CC: [action] (1.3) use all_forward -TK: I thin we can remove parenthesis (2.2.1) around derived from and use binary version of ... -TS: but then you need them at the end; I don't think is helpful -TK: (2.2.3) needs to check forward_iterator -TS: we are just making a C++17 forward into a C++20 input iterator - this is going to be pervasive -TS: having the category lie within the type it isn't that bad -TK: I would still prefer that not to lie if we can avoid it -TS: this one only lies if the iterator lies to us -TS: [action] 2.1 should say is_reference_v -TS: [action] all the other bullets need to start with "otherwise" -TK: I'd prefer using N < (sizeof...(Views) -TS: you'd still need the -1 -TK: [action] OK, we can keep it as is but I prefer < -RD: I put some formatting changes to the chat -TS: on prev(): the block is cartesian-common-arg and use that here: we could get rid of the constexpr -TS: [action] instead of ranges::size this should be ranges::distance and we don't need the static_cast -TS: [action] all the steps need to cast to that iterator's difference_type -TK: if we need to skip multiple ranges and we are emplacing all the iterators and this is observable -TS: if we skip a range entirely we just need to call distance -TS: [issue] do we want to avoid emplacing ranges we don't need to use? -TK: this applies to both advance forward and backward -TS: for advance backward we can also use the common logic -CC: the static_cast are not needed -TS: [action] you should use ranges::distance and then you don't need them -TS: [action] al the steps need to be cast to range::diffence_type -TK: the requirements for random access is too strict: we don't need sized for the last range -TK: we could use the same macro as for bidirectional -SLY: what TK brought we considered; I think that was discussed: there was a reason why we didn't go for that but I can't remember right now -TK: we could look at op- between iterator which is related: this one works -TK: the one with the sentinel need to require sized sentinel -SLY: we are still over constrained for some reason -TS: we don't need sized sentinel: we can get (it - begin) -JG: [action] explain why this is over-constrained -TK: if we think the last range is special for bidirectional it should be consistently special -DK: can we figure that out off-line? -JG: we will certainly need to see this paper again but let's go through all sections -CC: [action] the use of maybe-const on the requirement of the constructor: I think we removed them elsewhere as we Const is true -JG: did we have this in the synopsis as well? -TK: [action] for op*() p10 can use concat_reference_t -TS: [action] we don't need the preconditions: they come from the "Equivalent to:" => strike p13 and p15 -DK: also p17 and p19? -TS: [action] you need p17 but you can rid of p19 -RD: where does "reference" come from? -TS: [action] we should spell out what reference is in 2.1 -TK: in the op[] I'd prefer that we get an iterator i and then dereference *i and we don't say how we get it -JG: are the precondition needed here? -DK: I think when we have "Equivalent To" and it says on the equivalent things we can drop them -CC: I'd prefer the precondition on the op== -TS: can we drop the precondition and rather say in the front-matter say "if valueless_by_acception() is true the iterator is singular" -CC: it isn't directly clear to me that I can't operate on singular iterators and they kind of override the generic requirements -CC: we can do it at least with front matter for this iterator -TS: if you think singular is insufficient, we can say that all operations on singular iterators for concat iterator undefined -TS: [action] put the front matter after the iterator_category -TK: [action] we should use a single definition for the relational operators similar to basic_const_iterator -[const.iterator.ops] p19 -TK: I'll provide a better link -TK: op- for default_sentinel/iterator looks odd -TK: I would prefer to use this is the primary and the other direction negative; it isn't wrong though -CC: iterator const& needs to be fixed to become const iterator& -TK: if we factor maybe-const types in the exception specification should be better -TK: do we want to compute the conditional noexcept on all combination? -TS: that is quadratic -CC: the visit is on the same complexity -TK: I'm not sure if iter_swap behaves correctly when the common_reference_t is prvalues -TS: is that an indirectly swappable thing? -CC: this is a question about iter_swap not about this paper -TK: over here we are hiding swapping iterators with different types behind an interface with one type -TK: we should require the reference types to be swappable -CC: that is circular -TS: I think the authors need to think about iter_swap and provide rational +- JG: this is for C++26 +- JG presenting +- TK: do we still use tie? +- TS: this paper doesn't actually use tuple or pair +- TS: 5.2 is already done +- JG: this came in with zip or so. +- TS: [action] 5.2 needs to go +- TK: what about concat of no views? +- JG: don't do that +- TS: ill-formed +- CC: [action] we don't need 24.7.?.1 p2.3 and strick "if this expression is well formed" from 2.2 +- TK: do we want to allow concat_view of one view +- RD: the pre-matter does talk about 0 and 1 view and it is all_view +- TK: but I can still use concat_view explicitly with 1 object +- TS: that doesn't seem justified: you can get a take_view of a string_view and get a string_view back +- TK: do we have common_reference_t with single argument? +- TS: I'm pretty sure we do: we can have it with any number of argument > 0 +- TS: we should change the example to use print instead of cout +- JG: is there something special about concat-random-access which we don't have under some other concept? +- CC: in general these concepts are models requirements and are needed when implementing the view +- TK: [action] when doing zip_view and cartesian_product we added maybe_const so we don't need to do that everywhere and we should do that here, too +- RD: do we have a recommended way to word the concepts like the concept-indriectly-readable +- RD: how consistent do we want these wordings to be be? +- RD: the approach used here is otherwise only by iota_view +- RD: there is "exposition-only" repeated for iota_view +- JG: [action] in 24.7.?.2 add exposition-only for these concepts +- JG: we tend to remove the section names +- TS: the concept uses static_cast - where do we require the implicit conversion work? +- TK: we required common_refernce_t but not common_reference_with +- CC: this is the impl-version; the other requires common_reference_with +- TS: we require each of the iterator types to have something convertible_to but I don't see we check that +- JG: so we have a required change +- TS: it should require convertible_to in addition to the two expressions +- TS: if you do things multiple times you end up getting totally nonsensical result +- TK: do you mean implicate conversions? +- CC: do we change to the requires expression to what I typed in the chat? +- TS: [action] we need to require the entire expression to be equality preserving: we could add CC's code +- TK: I have another variation how to spell that in the chat +- TS: we can do that, too - I don't mind how we spell it +- TK: I believe it is the same thing +- RD: [action] on p3 the pack needs to be expanded as I put into the chat +- TS: the types model a concept; this one is ugly +- TS: it needs to say both satisfies and models +- JG: why the requirement on 3.2? +- CC: we should add a "The" at the begining of 3.1 +- CC: [action] that "expect" needs to be "except" +- TS: I'd like to say this in code instead of word - or pseudo code +- JG: TS's homework is to put suggested wording into the chat or send it to the author +- TK: for the end: the last element is always the last element of the pack and then we can apply constness when needed (see chat) +- TS: on the concept view: we don't need the default_initializable +- JG: [action] remove the requires from the default constructor an remove the initialization of views_ +- TK: [action] in the size the make_unsigned_t should be make_unsigned_like_t as it could be integer-like +- RD: the as_const stuff is just missing an article in multiple places +- CC: [action] on size() the {} need to be () +- TS: [action] also CT(0) isn't needed - the sequence is always non-empty +- TK: [action] value_type could use concat_value_t +- TS: the maybe-const needs to be there +- JG: unless we restructure as TK has mentioned +- TK: [action] we don't need the friends +- JG: do we need the = base-iter();? +- TK: it is a variant: it will construct the first element +- TK: [action] the requires on the default ctor isn't needed +- TK: [action] and remove initialization from base-iter() +- TS: it is weird that the default is tied to the first iterator in the range specifically +- DK: the default ctor doesn't mean anything +- TS: yes, it can only be compared to itself +- DK: so we could have a special variant member +- TS: it could use monostate instead of depending on the first iterator +- TS: I would add monostate to the end and initialize with that +- TK: but why at the end? +- TS: I think it is nicer at the end if we add monostate +- TK: I'd be more comfortable that it is default constructible if any iterator is default constructable +- TS: that is harder to implement; it is simple to add monostate and always use that +- TS: but then everything visiting the variant is harder - so I take that back: I think I can accept the weirdness +- RD: [action] op-- is missing a ; +- TK: [action] for the op++ and the others we should use the random-access from zip_view +- TS: [action] the concepts from zip_view [rang.zip.iterator] need to move to a different section: move to [range.utility.helper] +- TS: maybe we should promote [range.utility.helper] to something higher +- CC: seems odd that we have compile-time and run-time range helper; this is a change which can be done outside this paper +- TK: all the relational operators should use the random-access +- JG: [action] the things which use the general concepts are replaced: op++, op<, etc. +- CC: [action] there is iterator const& which should be const iterator& (this is editorial) +- CC: [action] (1.3) use all_forward +- TK: I thin we can remove parenthesis (2.2.1) around derived from and use binary version of ... +- TS: but then you need them at the end; I don't think is helpful +- TK: (2.2.3) needs to check forward_iterator +- TS: we are just making a C++17 forward into a C++20 input iterator - this is going to be pervasive +- TS: having the category lie within the type it isn't that bad +- TK: I would still prefer that not to lie if we can avoid it +- TS: this one only lies if the iterator lies to us +- TS: [action] 2.1 should say is_reference_v +- TS: [action] all the other bullets need to start with "otherwise" +- TK: I'd prefer using N < (sizeof...(Views) +- TS: you'd still need the -1 +- TK: [action] OK, we can keep it as is but I prefer < +- RD: I put some formatting changes to the chat +- TS: on prev(): the block is cartesian-common-arg and use that here: we could get rid of the constexpr +- TS: [action] instead of ranges::size this should be ranges::distance and we don't need the static_cast +- TS: [action] all the steps need to cast to that iterator's difference_type +- TK: if we need to skip multiple ranges and we are emplacing all the iterators and this is observable +- TS: if we skip a range entirely we just need to call distance +- TS: [issue] do we want to avoid emplacing ranges we don't need to use? +- TK: this applies to both advance forward and backward +- TS: for advance backward we can also use the common logic +- CC: the static_cast are not needed +- TS: [action] you should use ranges::distance and then you don't need them +- TS: [action] al the steps need to be cast to range::diffence_type +- TK: the requirements for random access is too strict: we don't need sized for the last range +- TK: we could use the same macro as for bidirectional +- SLY: what TK brought we considered; I think that was discussed: there was a reason why we didn't go for that but I can't remember right now +- TK: we could look at op- between iterator which is related: this one works +- TK: the one with the sentinel need to require sized sentinel +- SLY: we are still over constrained for some reason +- TS: we don't need sized sentinel: we can get (it - begin) +- JG: [action] explain why this is over-constrained +- TK: if we think the last range is special for bidirectional it should be consistently special +- DK: can we figure that out off-line? +- JG: we will certainly need to see this paper again but let's go through all sections +- CC: [action] the use of maybe-const on the requirement of the constructor: I think we removed them elsewhere as we Const is true +- JG: did we have this in the synopsis as well? +- TK: [action] for op*() p10 can use concat_reference_t +- TS: [action] we don't need the preconditions: they come from the "Equivalent to:" => strike p13 and p15 +- DK: also p17 and p19? +- TS: [action] you need p17 but you can rid of p19 +- RD: where does "reference" come from? +- TS: [action] we should spell out what reference is in 2.1 +- TK: in the op[] I'd prefer that we get an iterator i and then dereference *i and we don't say how we get it +- JG: are the precondition needed here? +- DK: I think when we have "Equivalent To" and it says on the equivalent things we can drop them +- CC: I'd prefer the precondition on the op== +- TS: can we drop the precondition and rather say in the front-matter say "if valueless_by_acception() is true the iterator is singular" +- CC: it isn't directly clear to me that I can't operate on singular iterators and they kind of override the generic requirements +- CC: we can do it at least with front matter for this iterator +- TS: if you think singular is insufficient, we can say that all operations on singular iterators for concat iterator undefined +- TS: [action] put the front matter after the iterator_category +- TK: [action] we should use a single definition for the relational operators similar to basic_const_iterator +- [const.iterator.ops] p19 +- TK: I'll provide a better link +- TK: op- for default_sentinel/iterator looks odd +- TK: I would prefer to use this is the primary and the other direction negative; it isn't wrong though +- CC: iterator const& needs to be fixed to become const iterator& +- TK: if we factor maybe-const types in the exception specification should be better +- TK: do we want to compute the conditional noexcept on all combination? +- TS: that is quadratic +- CC: the visit is on the same complexity +- TK: I'm not sure if iter_swap behaves correctly when the common_reference_t is prvalues +- TS: is that an indirectly swappable thing? +- CC: this is a question about iter_swap not about this paper +- TK: over here we are hiding swapping iterators with different types behind an interface with one type +- TK: we should require the reference types to be swappable +- CC: that is circular +- TS: I think the authors need to think about iter_swap and provide rational diff --git a/concat.md b/concat.md index f30f4e8..608f638 100644 --- a/concat.md +++ b/concat.md @@ -757,7 +757,7 @@ namespace std::ranges{ `(forward_range<@_maybe-const_@>&&...)` is modeled. In that case, `iterator::iterator_category` is defined as follows: -- [2.1]{.pnum} If `is_reference_v` is `false`, then +- [2.1]{.pnum} If `is_reference_v<@*concat-reference-t*@<@_maybe-const_@...>>` is `false`, then `iterator_category` denotes `input_iterator_tag` - [2.2]{.pnum} Otherwise, let `Cs` denote the pack of types `iterator_traits>>::iterator_category...`. @@ -780,7 +780,7 @@ constexpr void @_satisfy_@(); // exposition only [3]{.pnum} *Effects*: Equivalent to: ```cpp -if constexpr (N != (sizeof...(Views) - 1)) { +if constexpr (N < (sizeof...(Views) - 1)) { if (get(@*it_*@) == ranges::end(get(@*parent_*@->@*views_*@))) { @*it_*@.template emplace(ranges::begin(get(@*parent_*@->@*views_*@))); @*satisfy*@(); @@ -914,7 +914,7 @@ constexpr decltype(auto) operator*() const; [10]{.pnum} *Effects*: Equivalent to: ```cpp -using reference = common_reference_t>...>; +using reference = @*concat-reference-t*@<@_maybe-const_@...>; return std::visit([](auto&& it) -> reference { return *it; }, @*it_*@); ``` @@ -945,9 +945,7 @@ constexpr void operator++(int); :::bq -[13]{.pnum} *Preconditions*: `@*it_*@.valueless_by_exception()` is `false`. - -[14]{.pnum} *Effects*: Equivalent to: +[13]{.pnum} *Effects*: Equivalent to: ```cpp ++*this; @@ -962,9 +960,7 @@ constexpr @_iterator_@ operator++(int) :::bq -[15]{.pnum} *Preconditions*: `@*it_*@.valueless_by_exception()` is `false`. - -[16]{.pnum} *Effects*: Equivalent to: +[14]{.pnum} *Effects*: Equivalent to: ```cpp auto tmp = *this; @@ -981,9 +977,9 @@ constexpr @_iterator_@& operator--() :::bq -[17]{.pnum} *Preconditions*: `@*it_*@.valueless_by_exception()` is `false`. +[15]{.pnum} *Preconditions*: `@*it_*@.valueless_by_exception()` is `false`. -[18]{.pnum} *Effects*: Let `@*i*@` be `@*it_*@.index()`. Equivalent to: +[16]{.pnum} *Effects*: Let `@*i*@` be `@*it_*@.index()`. Equivalent to: ```cpp @*prev*@<@*i*@>(); @@ -999,9 +995,7 @@ constexpr @_iterator_@ operator--(int) :::bq -[19]{.pnum} *Preconditions*: `@*it_*@.valueless_by_exception()` is `false`. - -[20]{.pnum} *Effects*: Equivalent to: +[17]{.pnum} *Effects*: Equivalent to: ```cpp auto tmp = *this; @@ -1018,9 +1012,9 @@ constexpr @_iterator_@& operator+=(difference_type n) :::bq -[21]{.pnum} *Preconditions*: `@*it_*@.valueless_by_exception()` is `false`. +[18]{.pnum} *Preconditions*: `@*it_*@.valueless_by_exception()` is `false`. -[22]{.pnum} *Effects*: Let `@*i*@` be `@*it_*@.index()`. Equivalent to: +[19]{.pnum} *Effects*: Let `@*i*@` be `@*it_*@.index()`. Equivalent to: ```cpp if(n > 0) { @@ -1040,9 +1034,9 @@ constexpr @_iterator_@& operator-=(difference_type n) :::bq -[23]{.pnum} *Preconditions*: `@*it_*@.valueless_by_exception()` is `false`. +[20]{.pnum} *Preconditions*: `@*it_*@.valueless_by_exception()` is `false`. -[24]{.pnum} *Effects*: Equivalent to: +[21]{.pnum} *Effects*: Equivalent to: ```cpp *this += -n; @@ -1058,9 +1052,9 @@ constexpr decltype(auto) operator[](difference_type n) const :::bq -[25]{.pnum} *Preconditions*: `@*it_*@.valueless_by_exception()` is `false`. +[22]{.pnum} *Preconditions*: `@*it_*@.valueless_by_exception()` is `false`. -[26]{.pnum} *Effects*: Equivalent to: +[23]{.pnum} *Effects*: Equivalent to: ```cpp return *((*this) + n); @@ -1075,10 +1069,10 @@ friend constexpr bool operator==(const @_iterator_@& x, const @_iterator_@& y) :::bq -[27]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and +[24]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and `y.@*it_*@.valueless_by_exception()` are each `false`. -[28]{.pnum} *Effects*: Equivalent to: +[25]{.pnum} *Effects*: Equivalent to: ```cpp return x.@*it_*@ == y.@*it_*@; @@ -1092,9 +1086,9 @@ friend constexpr bool operator==(const @_iterator_@& it, default_sentinel_t); :::bq -[29]{.pnum} *Preconditions*: `it.@*it_*@.valueless_by_exception()` is `false`. +[26]{.pnum} *Preconditions*: `it.@*it_*@.valueless_by_exception()` is `false`. -[30]{.pnum} *Effects*: Equivalent to: +[27]{.pnum} *Effects*: Equivalent to: ```cpp constexpr auto last_idx = sizeof...(Views) - 1; @@ -1111,10 +1105,10 @@ friend constexpr bool operator<(const @_iterator_@& x, const @_iterator_@& y) :::bq -[31]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and +[28]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and `y.@*it_*@.valueless_by_exception()` are each `false`. -[32]{.pnum} *Effects*: Equivalent to: +[29]{.pnum} *Effects*: Equivalent to: ```cpp return x.@*it_*@ < y.@*it_*@; @@ -1129,10 +1123,10 @@ friend constexpr bool operator>(const @_iterator_@& x, const @_iterator_@& y) :::bq -[33]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and +[30]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and `y.@*it_*@.valueless_by_exception()` are each `false`. -[34]{.pnum} *Effects*: Equivalent to: +[31]{.pnum} *Effects*: Equivalent to: ```cpp return y < x; @@ -1147,10 +1141,10 @@ friend constexpr bool operator<=(const @_iterator_@& x, const @_iterator_@& y) :::bq -[35]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and +[32]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and `y.@*it_*@.valueless_by_exception()` are each `false`. -[36]{.pnum} *Effects*: Equivalent to: +[33]{.pnum} *Effects*: Equivalent to: ```cpp return !(y < x); @@ -1165,10 +1159,10 @@ friend constexpr bool operator>=(const @_iterator_@& x, const @_iterator_@& y) :::bq -[37]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and +[34]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and `y.@*it_*@.valueless_by_exception()` are each `false`. -[38]{.pnum} *Effects*: Equivalent to: +[35]{.pnum} *Effects*: Equivalent to: ```cpp return !(x < y); @@ -1184,10 +1178,10 @@ friend constexpr auto operator<=>(const @_iterator_@& x, const @_iterator_@& y) :::bq -[39]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and +[36]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and `y.@*it_*@.valueless_by_exception()` are each `false`. -[40]{.pnum} *Effects*: Equivalent to: +[37]{.pnum} *Effects*: Equivalent to: ```cpp return x.@*it_*@ <=> y.@*it_*@; @@ -1202,9 +1196,9 @@ friend constexpr @_iterator_@ operator+(const @_iterator_@& it, difference_type :::bq -[41]{.pnum} *Preconditions*: `it.@*it_*@.valueless_by_exception()` is `false`. +[38]{.pnum} *Preconditions*: `it.@*it_*@.valueless_by_exception()` is `false`. -[42]{.pnum} *Effects*: Equivalent to: +[39]{.pnum} *Effects*: Equivalent to: ```cpp return @_iterator_@{it} += n; @@ -1219,9 +1213,9 @@ friend constexpr @_iterator_@ operator+(difference_type n, const @_iterator_@& i :::bq -[43]{.pnum} *Preconditions*: `it.@*it_*@.valueless_by_exception()` is `false`. +[40]{.pnum} *Preconditions*: `it.@*it_*@.valueless_by_exception()` is `false`. -[44]{.pnum} *Effects*: Equivalent to: +[41]{.pnum} *Effects*: Equivalent to: ```cpp return it + n; @@ -1236,9 +1230,9 @@ friend constexpr @_iterator_@ operator-(const @_iterator_@& it, difference_type :::bq -[45]{.pnum} *Preconditions*: `it.@*it_*@.valueless_by_exception()` is `false`. +[42]{.pnum} *Preconditions*: `it.@*it_*@.valueless_by_exception()` is `false`. -[46]{.pnum} *Effects*: Equivalent to: +[43]{.pnum} *Effects*: Equivalent to: ```cpp return @*iterator*@{it} -= n; @@ -1253,13 +1247,13 @@ friend constexpr difference_type operator-(const @_iterator_@& x, const @_iterat :::bq -[47]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and +[44]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` and `y.@*it_*@.valueless_by_exception()` are each `false`. -[48]{.pnum} *Effects*: Let `@*i~x~*@` denote `x.@*it_*@.index()` and `@*i~y~*@` +[45]{.pnum} *Effects*: Let `@*i~x~*@` denote `x.@*it_*@.index()` and `@*i~y~*@` denote `y.@*it_*@.index()` -- [48.1]{.pnum} if `@*i~x~*@ > @*i~y~*@`, let `@*d~y~*@` denote the distance +- [45.1]{.pnum} if `@*i~x~*@ > @*i~y~*@`, let `@*d~y~*@` denote the distance from `get<@*i~y~*@>(y.@*it_*@)` to the end of `get<@*i~y~*@>(y.@*parent_*@.@*views_*@)`, `@*d~x~*@` denote the distance from the begin of `get<@*i~x~*@>(x.@*parent_*@.@*views_*@)` to @@ -1272,13 +1266,13 @@ denote `y.@*it_*@.index()` return static_cast(@*d~y~*@) + s + static_cast(@*d~x~*@); ``` -- [48.2]{.pnum} otherwise, if `@*i~x~*@ < @*i~y~*@`, equivalent to: +- [45.2]{.pnum} otherwise, if `@*i~x~*@ < @*i~y~*@`, equivalent to: ```cpp return -(y - x); ``` -- [48.3]{.pnum} otherwise, equivalent to: +- [45.3]{.pnum} otherwise, equivalent to: ```cpp return static_cast(get<@*i~x~*@>(x.@*it_*@) - get<@*i~y~*@>(y.@*it_*@)); @@ -1293,9 +1287,9 @@ friend constexpr difference_type operator-(const @_iterator_@& x, default_sentin :::bq -[49]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` is `false`. +[46]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` is `false`. -[50]{.pnum} *Effects*: Let `@*i~x~*@` denote `x.@*it_*@.index()`, `@*d~x~*@` +[47]{.pnum} *Effects*: Let `@*i~x~*@` denote `x.@*it_*@.index()`, `@*d~x~*@` denote the distance from `get<@*i~x~*@>(x.@*it_*@)` to the end of `get<@*i~x~*@>(x.@*parent_*@.@*views_*@)`. For every integer `@*i~x~*@ < @*i*@ < sizeof...(Views)`, let `s` denote the sum of the sizes of @@ -1315,9 +1309,9 @@ friend constexpr difference_type operator-(default_sentinel_t, const @_iterator_ :::bq -[51]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` is `false`. +[48]{.pnum} *Preconditions*: `x.@*it_*@.valueless_by_exception()` is `false`. -[52]{.pnum} *Effects*: Equivalent to: +[49]{.pnum} *Effects*: Equivalent to: ```cpp return -(x - default_sentinel); @@ -1331,9 +1325,9 @@ friend constexpr decltype(auto) iter_move(const iterator& it) noexcept(@*see bel :::bq -[53]{.pnum} *Preconditions*: `it.@*it_*@.valueless_by_exception()` is `false`. +[50]{.pnum} *Preconditions*: `it.@*it_*@.valueless_by_exception()` is `false`. -[54]{.pnum} *Effects*: Equivalent to: +[51]{.pnum} *Effects*: Equivalent to: ```cpp return std::visit( @@ -1344,7 +1338,7 @@ return std::visit( it.@*it_*@); ``` -[55]{.pnum} *Remarks*: The exception specification is equivalent to: +[52]{.pnum} *Remarks*: The exception specification is equivalent to: ```cpp ((is_nothrow_invocable_v>>...`, `is_nothrow_invocable_v` is true. -[59]{.pnum} *Remarks*: The expression in the requires-clause is `true` if and +[56]{.pnum} *Remarks*: The expression in the requires-clause is `true` if and only if: For every combination of two types `X` and `Y` in the set of all types in the parameter pack `iterator_t<@_maybe-const_@>>...`, `indirectly_swappable` is modelled. diff --git a/impl/concat/concat.hpp b/impl/concat/concat.hpp index ea34b56..0bb12bc 100644 --- a/impl/concat/concat.hpp +++ b/impl/concat/concat.hpp @@ -186,7 +186,7 @@ concept has_tag = derived_from>:: template consteval auto iter_cat_test() { using reference = common_reference_t>...>; - if constexpr (!is_lvalue_reference_v) { + if constexpr (!is_reference_v) { return input_iterator_tag{}; } else if constexpr ((has_tag> && ...) && @@ -255,7 +255,7 @@ class concat_view : public view_interface> { template constexpr void satisfy() { - if constexpr (N != (sizeof...(Views) - 1)) { + if constexpr (N < (sizeof...(Views) - 1)) { if (get(it_) == ranges::end(get(parent_->views_))) { it_.template emplace(ranges::begin(get(parent_->views_))); satisfy(); @@ -338,7 +338,7 @@ class concat_view : public view_interface> { , it_{std::move(i.it_)} {} constexpr decltype(auto) operator*() const { - using reference = common_reference_t>...>; + using reference = xo::concat_reference_t<__maybe_const...>; return visit([](auto&& it) -> reference { return *it; }, it_); }