Why aren't container comparison operators allocator agnostic?

87 Views Asked by At

The comparison operators for containers require a matching allocator type, e.g. see the std::vector comparison operators.

That doesn't appear necessary to me… intuitively, all the operator needs to do is to compare the sizes of the containers and their elements. It shouldn't matter where the memory they're stored in came from.

Is there a deeper reason for this or is it just because this was not considered a relevant use case?

Expected: std::vector (e.g.) comparison operators to be defined for dissimilar allocators, e.g. std::allocator<int> (LHS) and std::pmr::polymorphic_allocator<int> (RHS).

Actual: std::vector comparison operators only declared for LHS and RHS with same allocator type, as per cppreference.com.

1

There are 1 best solutions below

0
Alexander Mihail On

I lived my entire professional life under the radar, never commented, never voted in forums, never asked questions. Made an account here recently to post an answer into a matter that affected me and others here quite personally, but had no reputation to do it. My searching for random opened questions that I could actually comprehend has brought me here.

Now, the more I think about an answer, the more I feel that your question is indeed quite fundamental, going to the essence of STL and that of other technologies. I am old enough to have lived through the beginnings of this industry and seen many of its convulsions. I think about all our struggles over the decades that have turned so religious, and about the moments in history where the industry has made some really bad turns. I believe the advent of STL in the late 90’s was one such turn, at a time when C++ could have gone on a simpler and clearer path if, for example, it allowed Pascal-like functions-in-functions.

The most important struggle of all times is over memory management. What we are all trying to achieve is algorithms running over a liquid memory substrate. Some have determined that in order to get there, we would actually need new languages where memory is, by design, abstracted away from the algorithm e.g. C#, Java. While going down that path, the designers have broken the one thing that is paramount to many of us: the cohesion of structures. In languages like that, you are not even allowed entertain the idea of asking for offsetof(structure.field), and sizeof(structure) is a fiercely guarded secret. You are also not allowed to assume that in struct {SomeType a; SomeOtherType b;}, fields a and b are adjacent in a memory layout.

C++’s answer to this algorithm/allocation separation is STL. The algorithms of STL use container iterators abstracted away from the user’s elemental data types. Behind the scenes, containers are also detached from the underlying memory allocation. Since they need performance, algorithms can and need to exploit the properties (axioms) of the underlying allocators. What STL is trying to achieve, is to get the allocator to freely shift, grow, and shrink elements and ranges while the upper algorithm is running and as the iterators are iterating. An incredible level of sophistication stems from here. C++ is now having to import heavily from Algebra of Categories. Everything now has to be axiomatic and tractable. You replace good-old debugging with scientific proofing.

Allocator is not only an argument for the comparison operator, but for all operations. Let’s sample this for the index operator []... It too takes the allocator argument. So, perhaps moving elements around while iterating over their containers is possible. It’s unfinished business, though, and feels like a trap. Down that way, one would surely need to interop between STL and the rest of C++, just as per manged vs. unmanaged in C#. Also, let’s give this a thought: what are these && rvalue references all about, really? I see a trend for STL and BOOST to become a dotNET tucked-up in header-files.

Another reason for promoting allocators everywhere is the promise of better performance. Within the same allocator, pointers and references are totally comparable. So equivalence == can be tested at reference level without going into content.

Please note that I was faithfully trying to help and share a point of view. I am now going to brace myself for the barrage of down-votes that are sure to come. Regards.