C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Draft Proposal of std::contains Utilities to the C++ Standard Library

From: Giuseppe D'Angelo <giuseppe.dangelo_at_[hidden]>
Date: Fri, 1 Mar 2024 12:04:49 +0100
Hello,

Il 01/03/24 06:45, Robert Sitton via Std-Proposals ha scritto:
> Hello again! I am here to propose the addition of three new utility
> functions to the C++ Standard Library: std::contains, std::contains_any,
> and std::contains_all. These functions are intended to improve direct
> and efficient queries on containers and ranges, filling a gap in the
> current C++ standard that affects both the readability and
> maintainability of code.
>
> Here's a quick outline of the proposed utilities:
>
> * std::contains: checking for a single value within a range or container.
> * std::contains_any: Determines if any of a set of specified values
> exist within a range or container.
> * std::contains_all: ensures all specified values are present within a
> range or container.

I'm profoundly puzzled by this proposal.


* Right now your std::contains specification *is* std::ranges::contains.

https://eel.is/c++draft/alg.contains

Why should we have duplicate functionality?

* std::contains_any also already "almost" exists
(std::ranges::find_first_of), so once more, what's the goal here?

* Your functions are defined on ranges, and as such, should live in the
std::ranges namespace. Why are they not there?


> These utilities utilize concepts for compile-time type checks to ensure
> compatibility and usability, and they are defined for all STL
> containers, strings, and ranges. Their implementation guarantees
> efficiency by using std::ranges::find, std::ranges::any_of, and
> std::ranges::all_of.

This sounds precisely what *not* to do, and how to guarantee terrible
efficiency.

If you want to check if a std::unordered_set contains a value, you call
`set.contains(value)`. You certainly don't want to call
`ranges::find(set.begin(), set.end(), value)`, turning a avg. O(1)
operation into a O(N).

`std::contains` as a generic operation only makes sense if it's a
customization point, with `std::ranges::contains` (...why bother with
find?) as a linear fallback in case the container doesn't know any better.

And even then, I'd argue that I want first and foremost to have
`std::vector<T>::contains` (ditto for all the other containers). I'm
sick and tired of disrespecting C++ users by not offering them this sort
of super-basic convenience, in the name of "purity" and "minimalistic"
interfaces. It only took [checks notes] *25 years* to finally have
std::string::contains; I hope the tide is turning.

So, IMHO, the only possible rationale for something like
`std::ranges::contains_any` should be "it's a shortcut for
`find_first_of(b, e, v) != e`, just like `contains` is a shortcut for
`find(b, e, v) != e`". I don't have any data on how much this is really
needed (sounds like a niche use case), but I wouldn't necessarily oppose
the idea.



> The addition of std::contains and its related functions could be a major
> advancement in the way containers are manipulated in C++. These tools
> are highly beneficial for developers, providing them with the ability to
> write clearer, more efficient, and robust code. They also improve the
> readability of the code and reduce the amount of boilerplate required
> while focusing on expressiveness and intent. Additionally, these
> functions simplify common container operations, bringing C++ more in
> line with functionality found in other major programming languages.

These are extraordinary claims, unsupported by extraordinary evidence in
the paper. And, I repeat, I say that as someone who would love to have
vector::contains!



> I have attached a detailed proposal document to this email. This
> document includes a comprehensive rationale, technical specifications,
> implementation examples, and anticipated impact. I believe that these
> additions will be highly beneficial for the C++ community. I am eagerly
> looking forward to receiving your feedback and suggestions for further
> improvement.

* The "comprehensive" rationale is 4 lines.

* You say "Developers resort to verbose, error-prone patterns." and not
show even one of them.

* "offering concise, intuitive syntax that aligns with modern
programming practices." What programming practices? Did you run a survey
asking what developers would prefer between

1) if (std::ranges::contains(v, 42)) { ~~~ } // status quo
2) if (std::contains(v, 42)) { ~~~ } // proposal (?)
3) if (v.contains(42)) { ~~~ } // how it looks like in
every other programming language and what I'd love to see

?

* The technical specifications are highly imprecise/bugged, but that's
something to nail down after the design.




> This communication contains confidential information and may be
> privileged. If you are not the intended recipient or believe that you
> have received this communication in error, please reply to the sender
> indicating that fact and delete the copy you received. You should also
> not print, copy, re-transmit, disseminate, or otherwise use the
> information unless expressly indicated in this communication.

For the future: please get rid of this email suffix.

-- 
Giuseppe D'Angelo

Received on 2024-03-01 11:04:53