C++ Logo

std-proposals

Advanced search

Re: [std-proposals] : views::delimit

From: Hewill Kang <hewillk_at_[hidden]>
Date: Fri, 12 Apr 2024 21:55:02 +0800
Hi Barry,

Thanks for your valuable comment.

"First, it's unclear whether to save v just in a lambda or use
> bind_front(ranges::not_equal_to, v) for a more general purpose, which
> introduces extra indirection anyway with one more layer of wrapping."


I'm not sure what extra indirection you mean? I think bind_front is better,
> since then you can views::delimit(v) or views::delimit(std::ref(v)).


I mean if we just want to compare `*it == v`, in case of using `take_while`
implementation it will be done by `invoke(bind_front(ranges::not_equal_to,
v), *it)` --> `ranges::not_equal_to(*it , v)` --> `*it == v`. That is, we
have to pay the cost of two *extra* function calls.

I initially thought that the compiler would optimize out these function
calls. However, when I implemented `views::delimit` via `take_while` with
lambda and `bind_front` respectively in my local, I found that the assembly
code for using lambda under -O3 is the same as introducing a new
`delimit_view` class, but using `bind_front` produce more instructions. It
seems like the compiler is better at optimizing lambdas.

I don't know which one I should really use. Also, I'm not sure that the
compiler can optimize to the same performance as introducing the new
`delimit_view` class in *any* case.

"Second, we need to check that v can be forwarded into lambda, which
> requires additional constraints for the adaptor's call operator. Moreover,
> we also need to ensure that e != v is a valid expression to avoid hard
> errors in the lambda body, which ultimately makes the function signature
> complex and ugly."
>


> Yes, but you need all those same constraints anyway, right?


If using lambda, I have to add constraints to ensure that the construction
of lambda, i.e. `[v=forward<V>(v)](const auto& elem) -> bool { return v ==
elem; }` is a valid expression, but I can't just put it into the
`requires`-clause since both capture list and return statement can
produce *hard
errors*.
So I need to add `constructible_from<decay_t<V>, V>` and
`equality_comparable_with` to the adaptor's call operator (I'm not sure if
this is enough), which seems bloated. If a new `delimit_view` class is
introduced, I can just check whether `delimit_view(E, F)` is a valid
expression because the class already has the correct constraints.
The same goes for `bind_front` as it is not a constraint function. Since
the `delimit_view` class is not complicated, I think introducing it should
be okay.

"Finally, if the bottom layer of views::delimit is take_while_view, then
> the former will also have a pred() member which returns the internal
> lambda, this can lead to untold confusion for the user."
>


> I am, ironically, confused by this claim. If we just say delimit(v) is
> shorthand for take_while(bind_front(...)) then I think it's pretty clear
> what pred() means, right?


But when the user passes in a value, he can only get an *unspecified*
predicate. Personally, I find this a bit strange because I don't know the
point of getting such an unspecified object.

Hope I have clarified your question.

Best,
Hewill



Barry Revzin <barry.revzin_at_[hidden]> 於 2024年4月12日 週五 上午10:08寫道:

>
>
> On Thu, Apr 4, 2024 at 5:57 AM Hewill Kang via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Hi all,
>>
>> I wrote a draft for C++26 range adaptor views::delimit, you can see it
>> here
>> https://isocpp.org/files/papers/D3220R0.html
>> Since this is a draft, there may be some missing points that have not
>> been considered, or there is room for improvement in wording.
>> Comments are welcome.
>>
>> Thanks,
>> Hewill
>>
>
> Hey Hewil,
>
> I didn't understand the argument for why not just define delimit as
> take_while. You mean three points there:
>
> "First, it's unclear whether to save v just in a lambda or use
> bind_front(ranges::not_equal_to, v) for a more general purpose, which
> introduces extra indirection anyway with one more layer of wrapping."
>
> I'm not sure what extra indirection you mean? I think bind_front is
> better, since then you can views::delimit(v) or
> views::delimit(std::ref(v)).
>
> "Second, we need to check that v can be forwarded into lambda, which
> requires additional constraints for the adaptor's call operator. Moreover,
> we also need to ensure that e != v is a valid expression to avoid hard
> errors in the lambda body, which ultimately makes the function signature
> complex and ugly."
>
> Yes, but you need all those same constraints anyway, right?
>
> "Finally, if the bottom layer of views::delimit is take_while_view, then
> the former will also have a pred() member which returns the internal
> lambda, this can lead to untold confusion for the user."
>
> I am, ironically, confused by this claim. If we just say delimit(v) is
> shorthand for take_while(bind_front(...)) then I think it's pretty clear
> what pred() means, right?
>
> Thanks for writing this up,
>
> Barry
>

Received on 2024-04-12 13:55:15