Requesting endorsements of Boost.STLInterfaces for review
As mentioned a couple of weeks ago, I started a small library that was an updated iterator_facade. It is now a still-smallish library called stl_interfaces that includes a pre-C++20 implementation of view_interface, and analogous templates iterator_interface (a cross between Boost.Iterator's iterator_facade and iterator_adaptor), and container_interface. Each of these makes it easier to write a view, iterator, or container, respectively. Using container_interface, I was able to write a version of static_vector in which I implemented only 21 member functions, and the template provided the other 40(!) functions. The library is C++14 and later. There is an inline v1 namespace for the C++14 implementations, and an experimental non-inline v2 namespace with implementations using C++20 standard concepts. The part using C++20 concepts requires GCC 8 or 9, and cmcstl2 (more info on that on the Github page). Github page: https://github.com/tzlaine/stl_interfaces Online docs: https://tzlaine.github.io/stl_inteTherfaces/doc/html/index.html https://tzlaine.github.io/stl_interfaces/doc/html/index.html Oh, and if you're willing to act as review manager, please let me know. Zach
On 23/08/2019 14:11, Zach Laine wrote:
Online docs:
https://tzlaine.github.io/stl_inteTherfaces/doc/html/index.html https://tzlaine.github.io/stl_interfaces/doc/html/index.html
Speaking of iterators being error-prone (and the ironic typo in the above link): In https://tzlaine.github.io/stl_interfaces/doc/html/boost_stlinterfaces__propo... the long-form implementation of repeated_chars_iterator::operator>= is not correct. And operator-(difference_type lhs, repeated_chars_iterator rhs) seems dubious; this operation is normally not commutative. It seems more correct for that operator to not exist. (And I hope that iterator_interface does not define it either.) There's also several typos sprinkled around, such as "givenn" and using "if" instead of "it", etc. I haven't read this in detail yet, but it sounds interesting. Are you planning to add support for AllocatorAwareContainer at a later stage, or is there something that would make that infeasible?
On Thu, Aug 22, 2019 at 10:14 PM Gavin Lambert via Boost < boost@lists.boost.org> wrote:
On 23/08/2019 14:11, Zach Laine wrote:
Online docs:
https://tzlaine.github.io/stl_inteTherfaces/doc/html/index.html https://tzlaine.github.io/stl_interfaces/doc/html/index.html
Speaking of iterators being error-prone (and the ironic typo in the above link):
How'd that get in there? That's weird.
In
https://tzlaine.github.io/stl_interfaces/doc/html/boost_stlinterfaces__propo... the long-form implementation of repeated_chars_iterator::operator>= is not correct.
Thanks. I almost want to leave it for pedagogical reasons.
And operator-(difference_type lhs, repeated_chars_iterator rhs) seems dubious; this operation is normally not commutative. It seems more correct for that operator to not exist.
Yeah, that should not be there.
(And I hope that iterator_interface does not define it either.)
It does not.
There's also several typos sprinkled around, such as "givenn" and using "if" instead of "it", etc.
I just ran a spell-check on the docs. I think I got all the typos. I did not notice the if/it confusion. Where was that?
I haven't read this in detail yet, but it sounds interesting.
Are you planning to add support for AllocatorAwareContainer at a later stage, or is there something that would make that infeasible?
I hate allocators. I will not be adding support for allocator-aware containers. Thanks for the feedback. Does this mean that you'd like to see a review? Zach
On 23/08/2019 17:10, Zach Laine wrote:
There's also several typos sprinkled around, such as "givenn" and using "if" instead of "it", etc.
I just ran a spell-check on the docs. I think I got all the typos. I did not notice the if/it confusion. Where was that?
container_interface: "because if has no insert()".
Are you planning to add support for AllocatorAwareContainer at a later stage, or is there something that would make that infeasible?
I hate allocators. I will not be adding support for allocator-aware containers.
Thanks for the feedback. Does this mean that you'd like to see a review?
In principle yes, though I don't think I've looked at it enough to warrant a formal endorsement. I don't really write new iterators or containers very often, and when I do, it's usually the allocators that are the pain point.
On Fri, Aug 23, 2019 at 2:35 AM Hans Dembinski via Boost < boost@lists.boost.org> wrote:
On 23. Aug 2019, at 09:22, Gavin Lambert via Boost < boost@lists.boost.org> wrote:
I don't really write new iterators or containers very often, and when I do, it's usually the allocators that are the pain point.
I second that.
So do I. But that does not mean you need help making allocator-aware containers. That means you need to stop making them. The bang-for-buck is terrible. How much time and complexity increase is required to add allocator support? And how many instantiations of your container C will use a non-default allocator? It is never worth it, unless you work at a place like Bloomberg, where heavy allocator use is part of the culture. Here are the allocator requirements: http://eel.is/c++draft/containers#tab:container.alloc.req . They are all special member functions, constructors, one typedef, and member swap(). A CRTP base cannot help you with even one of those. Even if I could do something to make allocator-aware containers easier to write, I would not, simply because the whole point of making container_interface is to make container authoring straightforward. If multiple allocation strategies are actually important, write multiple containers, each with the different strategy. The allocation scheme you use is an inherent part of the class's invariant maintenance, despite what the standard library would have you think. Zach
On 8/23/19 6:39 PM, Zach Laine via Boost wrote:
Even if I could do something to make allocator-aware containers easier to write, I would not, simply because the whole point of making container_interface is to make container authoring straightforward. If multiple allocation strategies are actually important, write multiple containers, each with the different strategy. The allocation scheme you use is an inherent part of the class's invariant maintenance, despite what the standard library would have you think.
Container properties, like element contiguity, list and complexity of operations, etc., and memory allocator are conceptually distinct. Implementing a container over a non-customizable allocator is viable as long as the allocator fits your use case. Which is unlikely to be the case when the container is part of a public generic library, such as Boost.Whatever. Furthermore, asking people to reimplement the container just to change the allocator is simply unreasonable. Implementation complexity of a container is often higher than that of an allocator, given that it often comes down to one of the function families like malloc/aligned_alloc/free. Even if it doesn't, an allocator should not be part of the container implementation anyway. Standard containers may be unnecessarilly complicated by the current allocator handling convention, but conceptually, that the container and the allocator are separate, is the right design choice.
On Fri, Aug 23, 2019 at 2:12 PM Andrey Semashev via Boost < boost@lists.boost.org> wrote:
On 8/23/19 6:39 PM, Zach Laine via Boost wrote:
Even if I could do something to make allocator-aware containers easier to write, I would not, simply because the whole point of making container_interface is to make container authoring straightforward. If multiple allocation strategies are actually important, write multiple containers, each with the different strategy. The allocation scheme you use is an inherent part of the class's invariant maintenance, despite
what
the standard library would have you think.
Container properties, like element contiguity, list and complexity of operations, etc., and memory allocator are conceptually distinct. Implementing a container over a non-customizable allocator is viable as long as the allocator fits your use case. Which is unlikely to be the case when the container is part of a public generic library, such as Boost.Whatever.
Furthermore, asking people to reimplement the container just to change the allocator is simply unreasonable. Implementation complexity of a container is often higher than that of an allocator, given that it often comes down to one of the function families like malloc/aligned_alloc/free. Even if it doesn't, an allocator should not be part of the container implementation anyway.
Standard containers may be unnecessarilly complicated by the current allocator handling convention, but conceptually, that the container and the allocator are separate, is the right design choice.
As I stated previously, this discussion is thoroughly moot. I cannot do anything in a CRTP base class like container_interface to help those who want to create allocator-aware containers. Your feelings about the allocator abstraction -- and mine as well -- are irrelevant to any discussion of stl_interfaces. If you care enough about this debate to start another thread, I'll follow you there. Zach
On 23. Aug 2019, at 21:58, Zach Laine via Boost
wrote: On Fri, Aug 23, 2019 at 2:12 PM Andrey Semashev via Boost < boost@lists.boost.org> wrote:
On 8/23/19 6:39 PM, Zach Laine via Boost wrote:
Even if I could do something to make allocator-aware containers easier to write, I would not, simply because the whole point of making container_interface is to make container authoring straightforward. If multiple allocation strategies are actually important, write multiple containers, each with the different strategy. The allocation scheme you use is an inherent part of the class's invariant maintenance, despite
what
the standard library would have you think.
Container properties, like element contiguity, list and complexity of operations, etc., and memory allocator are conceptually distinct. Implementing a container over a non-customizable allocator is viable as long as the allocator fits your use case. Which is unlikely to be the case when the container is part of a public generic library, such as Boost.Whatever.
Furthermore, asking people to reimplement the container just to change the allocator is simply unreasonable. Implementation complexity of a container is often higher than that of an allocator, given that it often comes down to one of the function families like malloc/aligned_alloc/free. Even if it doesn't, an allocator should not be part of the container implementation anyway.
Standard containers may be unnecessarilly complicated by the current allocator handling convention, but conceptually, that the container and the allocator are separate, is the right design choice.
As I stated previously, this discussion is thoroughly moot. I cannot do anything in a CRTP base class like container_interface to help those who want to create allocator-aware containers.
Your feelings about the allocator abstraction -- and mine as well -- are irrelevant to any discussion of stl_interfaces. If you care enough about this debate to start another thread, I'll follow you there.
I think Andrey gave you some very good arguments and we are not discussing personal choices here. Allocators are part of the STL and Boost. You need to adhere to these design choices if you want to write a generic C++ component that may be part of the STL some day. That it is too much effort for you is not a viable argument. Your arrogant and dismissive attitude is not helping your cause either. You are not becoming a first class C++ author by rejecting good advice.
On September 9, 2019 4:08:04 AM EDT, Hans Dembinski via Boost
On 23. Aug 2019, at 21:58, Zach Laine via Boost
wrote: As I stated previously, this discussion is thoroughly moot. I cannot do anything in a CRTP base class like container_interface to help those who want to create allocator-aware containers.
Your feelings about the allocator abstraction -- and mine as well -- are irrelevant to any discussion of stl_interfaces. If you care enough about this debate to start another thread, I'll follow you there.
I think Andrey gave you some very good arguments and we are not discussing personal choices here. Allocators are part of the STL and Boost. You need to adhere to these design choices if you want to write a generic C++ component that may be part of the STL some day. That it is too much effort for you is not a viable argument. Your arrogant and dismissive attitude is not helping your cause either. You are not becoming a first class C++ author by rejecting good advice.
You have completely missed the point. Zach is saying there is nothing that can be done, even if he wanted to do it, because the work has to be done in the derivate. Zach also is willing to discuss the topic, but doesn't want this thread derailed, which is perfectly reasonable. -- Rob (Sent from my portable computation device.)
On Mon, Sep 9, 2019 at 6:13 AM Rob Stewart via Boost
On September 9, 2019 4:08:04 AM EDT, Hans Dembinski via Boost < boost@lists.boost.org> wrote:
I think Andrey gave you some very good arguments and we are not discussing personal choices here. Allocators are part of the STL and Boost. You need to adhere to these design choices if you want to write a generic C++ component that may be part of the STL some day. That it is too much effort for you is not a viable argument. Your arrogant and dismissive attitude is not helping your cause either. You are not becoming a first class C++ author by rejecting good advice.
You have completely missed the point. Zach is saying there is nothing that can be done, even if he wanted to do it, because the work has to be done in the derivate.
Zach also is willing to discuss the topic, but doesn't want this thread derailed, which is perfectly reasonable.
Thanks, Rob. That's it exactly. It's not that allocator support is too hard, it's that it cannot be done with a CRTP adaptor. And I'm not trying to be rude, just trying to keep the thread focused. Email after does not convey tone of voice, after all. If I came off as rude or dismissive, I apologize. That was never my intention. Zach
I don't think I can formally endorse your library, but as I said before, I'd find something like this very useful and would be happy to see it getting a proper review by the boost community. Frankly speaking however, if you'd commit to maintaining the library as a standalone project on github (within a different namespace of course), that would be good enough for me. Best Mike
On Sat, Sep 7, 2019 at 12:10 PM Mike via Boost
I don't think I can formally endorse your library, but as I said before, I'd find something like this very useful and would be happy to see it getting a proper review by the boost community.
Frankly speaking however, if you'd commit to maintaining the library as a standalone project on github (within a different namespace of course), that would be good enough for me.
Thanks, Mike. By the way, what you just did counts as an endorsement. It's nothing formal, it's just an expressed interest in seeing a review. Zach
On Thu, Aug 22, 2019 at 9:11 PM Zach Laine
As mentioned a couple of weeks ago, I started a small library that was an updated iterator_facade. It is now a still-smallish library called stl_interfaces that includes a pre-C++20 implementation of view_interface, and analogous templates iterator_interface (a cross between Boost.Iterator's iterator_facade and iterator_adaptor), and container_interface.
[snip] Just a friendly reminder that this thread exist. :) There was quite a bit of interest when the thread had iterator_facade in the title; this is about that. Zach
On Tue, Aug 27, 2019 at 2:50 PM Zach Laine via Boost
On Thu, Aug 22, 2019 at 9:11 PM Zach Laine
wrote: As mentioned a couple of weeks ago, I started a small library that was an updated iterator_facade. It is now a still-smallish library called stl_interfaces that includes a pre-C++20 implementation of view_interface, and analogous templates iterator_interface (a cross between Boost.Iterator's iterator_facade and iterator_adaptor), and container_interface.
The before/after for the code is amazing, and that is does retain the same performance profile is great too. I would be very happy to have a library like this, especially after having written a large chunk of different encoding/decoding/transcoding iterators, and a handful of proxy iterators over the last few months. A pre-C++20 implementation of all of this would be fantastic. I do not really know how to weigh in on whether or not there should be container interfaces for allocators. There are a large portion of things to consider for allocator aware containers, with everything from strong exception safety to value_type rebinding when necessary to different storage methods for what the container has to do. Having started writing small_bit_buffer and small_buffer (SBO for bits-in-T, and SBO for just a plain T with no bit-based analysis) containers based on T/Alloc recently, I had an incredibly hard time trying to abstract away storage and size concerns in such a way that such things could be implemented in a plain generic fashion that did not incur space/time tradeoffs unacceptable in the places likely to use them. That is, I don't think allocator_container_interface is at all easy, or doable, as the usage of the allocator is extremely specific to the container you write. The rest of the library is lovely! :D Sincerely, JeanHeyd
On Tue, Aug 27, 2019 at 3:01 PM JeanHeyd Meneide
On Tue, Aug 27, 2019 at 2:50 PM Zach Laine via Boost < boost@lists.boost.org> wrote:
On Thu, Aug 22, 2019 at 9:11 PM Zach Laine
wrote: As mentioned a couple of weeks ago, I started a small library that was an updated iterator_facade. It is now a still-smallish library called stl_interfaces that includes a pre-C++20 implementation of view_interface, and analogous templates iterator_interface (a cross between Boost.Iterator's iterator_facade and iterator_adaptor), and container_interface.
The before/after for the code is amazing, and that is does retain the same performance profile is great too. I would be very happy to have a library like this, especially after having written a large chunk of different encoding/decoding/transcoding iterators, and a handful of proxy iterators over the last few months.
A pre-C++20 implementation of all of this would be fantastic.
I do not really know how to weigh in on whether or not there should be container interfaces for allocators. There are a large portion of things to consider for allocator aware containers, with everything from strong exception safety to value_type rebinding when necessary to different storage methods for what the container has to do. Having started writing small_bit_buffer and small_buffer (SBO for bits-in-T, and SBO for just a plain T with no bit-based analysis) containers based on T/Alloc recently, I had an incredibly hard time trying to abstract away storage and size concerns in such a way that such things could be implemented in a plain generic fashion that did not incur space/time tradeoffs unacceptable in the places likely to use them.
That is, I don't think allocator_container_interface is at all easy, or doable, as the usage of the allocator is extremely specific to the container you write. The rest of the library is lovely! :D
Thanks, JeanHeyd. I still do not think that I even *could* help. The reason is that the library's CRTP templates can only provide essentially vacuous implementations of functions that can be implemented in terms of the functions you provide. Any of the hairy parts of dealing with allocators would happen in the user-provided portion of the code. The CRTP template would provide one or more of these (from [tab:container.alloc.req], http://eel.is/c++draft/containers#tab:container.alloc.req): allocator_type get_allocator() X() X u; X(m) X u(m); X(t, m) X u(t, m); X(rv) X u(rv); X(rv, m) X u(rv, m); a = t a = rv a.swap(b) get_allocator() returns an allocator which is possibly a member variable. It must be user-provided. Member swap() must be user-provided; the CRTP template does not know enough about your type to implement that. The rest are a typedef, and the special members and constructors. The CRTP template cannot help with those either. Zach
Il mar 27 ago 2019, 20:50 Zach Laine via Boost
On Thu, Aug 22, 2019 at 9:11 PM Zach Laine
wrote: As mentioned a couple of weeks ago, I started a small library that was an updated iterator_facade. It is now a still-smallish library called stl_interfaces that includes a pre-C++20 implementation of view_interface, and analogous templates iterator_interface (a cross between Boost.Iterator's iterator_facade and iterator_adaptor), and container_interface.
[snip]
Just a friendly reminder that this thread exist. :) There was quite a bit of interest when the thread had iterator_facade in the title; this is about that.
Hi Zach, thanks for furthering your work. I would be glad to have something like this in Boost. As soon as possible I want to put your code to test: if there were a review I would try to participate in it. Best Francesco
On Thu, Aug 22, 2019 at 9:11 PM Zach Laine via Boost
As mentioned a couple of weeks ago, I started a small library that was an updated iterator_facade. It is now a still-smallish library called stl_interfaces that includes a pre-C++20 implementation of view_interface, and analogous templates iterator_interface (a cross between Boost.Iterator's iterator_facade and iterator_adaptor), and container_interface. Each of these makes it easier to write a view, iterator, or container, respectively. Using container_interface, I was able to write a version of static_vector in which I implemented only 21 member functions, and the template provided the other 40(!) functions.
The library is C++14 and later. There is an inline v1 namespace for the C++14 implementations, and an experimental non-inline v2 namespace with implementations using C++20 standard concepts. The part using C++20 concepts requires GCC 8 or 9, and cmcstl2 (more info on that on the Github page).
Github page:
https://github.com/tzlaine/stl_interfaces
Online docs:
https://tzlaine.github.io/stl_inteTherfaces/doc/html/index.html https://tzlaine.github.io/stl_interfaces/doc/html/index.html
Oh, and if you're willing to act as review manager, please let me know.
Zach
I'm a bit late to the party here, but I took a look at the updated github. I'm still excited about this library. It's obvious to me that a lot of thought and care has gone into it, and I would use it in a heartbeat. Boost would be remiss to overlook this for review.
_______________________________________________ Unsubscribe & other changes:
participants (9)
-
Andrey Semashev
-
Barrett Adair
-
Francesco Guerrieri
-
Gavin Lambert
-
Hans Dembinski
-
JeanHeyd Meneide
-
Mike
-
Rob Stewart
-
Zach Laine