Date: Sat, 3 Sep 2022 19:25:45 +0100
++ to what Barry said.
On Sat, Sep 3, 2022 at 6:26 PM Barry Revzin via Std-Proposals <
std-proposals_at_[hidden]> wrote:
>
>
> On Sat, Sep 3, 2022 at 3:49 AM Nikl Kelbon via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> std::generator has huge problems.
>> I will briefly list them:
>> 1. The generator must not depend on the allocator (only the promise_type
>> depends), but std::generator has a template argument for alloc, in
>> particular, this prohibits adding 2 generators that allocated memory
>> differently into a container. It is possible to implement this without type
>> erasure.
>> Link to example implementation:
>>
>> https://github.com/kelbon/dd_generator/blob/4053fcff456c885d9330708d2e67f103c4212319/include/dd_generator.hpp#L264
>>
>>
> I think what you're asking is, in this example:
>
> auto f(allocator_arg_t, CoolAllocator) -> std::generator<int>
>
> Should CoolAllocator be type-erased (current design) or not (since it's
> possible to go through coroutine_traits and have CoolAllocator be a
> template parameter of the promise type and stored directly)?
>
> Because the allocator is type-erased currently, it *is* possible to have
> multiple generators in a container that use different underlying
> allocators.
>
> But note that the current design allows:
>
> auto g() -> std::generator<int&, int, CoolAllocator>;
>
> Which obviates the need for passing extra function parameters, if
> CoolAllocator is default constructible. Having that seems useful.
>
>
>> 2. Overhead for ueslss default type erasure(default behavior) and stack
>> in generator (used only for element_of, which is basically for(auto&& v :
>> gen) co_yield v;
>> Its just uselss
>> You pay for what you dont use.
>>
>
> The paper claims otherwise - I'd like to see some support for this claim.
> How much overhead is there?
>
>
>> 3. It is undefined behavior to call begin for std::generator twice. But
>> iteraing not all values in one loop is a very logical action and expected
>> behavior - just keep generating values
>> Besides, such an error is extremely non-obvious when using ranges or
>> range based for loop.
>>
>
> This is not at all "a very logical action and expected behavior" - far,
> far from. This sort of stateful iteration is very much not the design of
> ranges, and has never been. If I see this in code:
>
> print("{}\n", v | views::take(4));
> print("{}\n", v | views::take(4));
>
> This had better either print the same (up to) four elements twice, or be
> undefined behavior. It is not at all logical or expected that it should
> print eight different elements. If you want to do that, you can just use
> the iterators directly and keep using the same iterator through multiple
> loops. This is totally fine, and would be clear to the reader what is going
> on.
>
> This is why it is undefined behavior to call begin() on *any *input range
> multiple times. Because you cannot iterate such a thing multiple times, and
> the way that most of these things (including generator) must be
> implemented, precludes any sort of sensible behavior.
>
>
>> 4. interface that is very obscure to the user and requires knowledge of
>> implementation to write efficient code
>> No one will write generator<const T&> foo(); without knowing why it is
>> needed and why it is better for perfmornace
>>
>
>> But there are way to write generator without such problems
>> https://github.com/kelbon/dd_generator
>>
>
> generator<const T&> is not a "very obscure" interface. If I want to have a
> generator that yields references to const, that seems to me like a fairly
> obvious thing to write. Also, in what way is it "better for performance"
> and what "knowledge of implementation" is needed "to write efficient code"?
> Some justification for these claims would be nice.
>
> Barry
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
On Sat, Sep 3, 2022 at 6:26 PM Barry Revzin via Std-Proposals <
std-proposals_at_[hidden]> wrote:
>
>
> On Sat, Sep 3, 2022 at 3:49 AM Nikl Kelbon via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> std::generator has huge problems.
>> I will briefly list them:
>> 1. The generator must not depend on the allocator (only the promise_type
>> depends), but std::generator has a template argument for alloc, in
>> particular, this prohibits adding 2 generators that allocated memory
>> differently into a container. It is possible to implement this without type
>> erasure.
>> Link to example implementation:
>>
>> https://github.com/kelbon/dd_generator/blob/4053fcff456c885d9330708d2e67f103c4212319/include/dd_generator.hpp#L264
>>
>>
> I think what you're asking is, in this example:
>
> auto f(allocator_arg_t, CoolAllocator) -> std::generator<int>
>
> Should CoolAllocator be type-erased (current design) or not (since it's
> possible to go through coroutine_traits and have CoolAllocator be a
> template parameter of the promise type and stored directly)?
>
> Because the allocator is type-erased currently, it *is* possible to have
> multiple generators in a container that use different underlying
> allocators.
>
> But note that the current design allows:
>
> auto g() -> std::generator<int&, int, CoolAllocator>;
>
> Which obviates the need for passing extra function parameters, if
> CoolAllocator is default constructible. Having that seems useful.
>
>
>> 2. Overhead for ueslss default type erasure(default behavior) and stack
>> in generator (used only for element_of, which is basically for(auto&& v :
>> gen) co_yield v;
>> Its just uselss
>> You pay for what you dont use.
>>
>
> The paper claims otherwise - I'd like to see some support for this claim.
> How much overhead is there?
>
>
>> 3. It is undefined behavior to call begin for std::generator twice. But
>> iteraing not all values in one loop is a very logical action and expected
>> behavior - just keep generating values
>> Besides, such an error is extremely non-obvious when using ranges or
>> range based for loop.
>>
>
> This is not at all "a very logical action and expected behavior" - far,
> far from. This sort of stateful iteration is very much not the design of
> ranges, and has never been. If I see this in code:
>
> print("{}\n", v | views::take(4));
> print("{}\n", v | views::take(4));
>
> This had better either print the same (up to) four elements twice, or be
> undefined behavior. It is not at all logical or expected that it should
> print eight different elements. If you want to do that, you can just use
> the iterators directly and keep using the same iterator through multiple
> loops. This is totally fine, and would be clear to the reader what is going
> on.
>
> This is why it is undefined behavior to call begin() on *any *input range
> multiple times. Because you cannot iterate such a thing multiple times, and
> the way that most of these things (including generator) must be
> implemented, precludes any sort of sensible behavior.
>
>
>> 4. interface that is very obscure to the user and requires knowledge of
>> implementation to write efficient code
>> No one will write generator<const T&> foo(); without knowing why it is
>> needed and why it is better for perfmornace
>>
>
>> But there are way to write generator without such problems
>> https://github.com/kelbon/dd_generator
>>
>
> generator<const T&> is not a "very obscure" interface. If I want to have a
> generator that yields references to const, that seems to me like a fairly
> obvious thing to write. Also, in what way is it "better for performance"
> and what "knowledge of implementation" is needed "to write efficient code"?
> Some justification for these claims would be nice.
>
> Barry
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2022-09-03 18:25:58