Date: Tue, 2 Jan 2024 15:46:04 -0600
I fully understand the concerns that have been raised about the proposed
std::contains function. However, it's important to emphasize that this
function is specifically designed to simplify common coding tasks. While
containers and ranges serve distinct purposes, having a unified
std::contains function can greatly benefit developers by promoting code
consistency and simplifying template code that works with various data
structures.
The introduction of this function aligns with C++'s goal of providing
standard, intuitive solutions for everyday programming tasks. It offers the
flexibility to customize behavior when needed, making it a valuable
addition to the C++ standard library (akin to std::find).
Sincerely,
Robert
On Sun, Dec 24, 2023, 2:41 PM Jason McKesson via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> On Sun, Dec 24, 2023 at 12:25 PM Giuseppe D'Angelo via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> >
> > Il 24/12/23 14:50, Ville Voutilainen via Std-Proposals ha scritto:
> > > On Sun, 24 Dec 2023 at 15:44, Bjorn Reese via Std-Proposals
> > > <std-proposals_at_[hidden]> wrote:
> > >>
> > >> On 12/23/23 10:20, Robert Sitton via Std-Proposals wrote:
> > >>
> > >>> Function Signature:
> > >>> template <typename Container, typename T>
> > >>> bool std::contains(const Container& container, const T& value);
> > >>
> > >> Why does it deviate from all other standard algorithms that takes
> > >> iterators (or ranges for std::ranges algorithms)?
> > >
> > > Because it doesn't operate on iterators. If you pass a std::map to it,
> > > it'll call std::map::contains,
> > > it doesn't perform a silly linear walk from one iterator to another.
> > > What we're looking at here is basically
> > > "call the argument's contains() if available, do a ranges::contains
> otherwise".
> >
> > Indeed; see also std::erase/erase_if, although for them there isn't even
> > a way to do the "otherwise" part -- the container must offer its own
> > overload, which effectively makes them customization points.
> >
> > My 2 c,
>
> The difference here is that what the "erase" functions do
> *fundamentally* cannot be done on a range. Ranges are sequences of
> elements, but they do not have a way to structurally manipulate the
> sequence of elements. The *contents* of those elements, yes. The
> actual sequence, no. As such, the "erase" class of functions do what
> the `remove` functions do, but they also include the container
> operations that actually get those elements out of the sequence.
>
> This is why they rely on the existence of member functions.
>
> That is not really the case for `contains`. Well it is, but it's also not.
>
> Like with "erase", what "contains" might do depends on the container
> itself. But unlike "erase", there is some reasonable, conceptual
> default functionality: search through the container in sequence for
> the item.
>
> But there are problems even with that. Associative container
> "contains" doesn't necessarily work like sequential container
> "contains" functions. And this is true at the API level. A sequential
> container "contains" function looks for equality with an element. An
> associative container "contains" function looks for "equality" with a
> *key* (or some type comparable with a key), not the actual value type.
> So it's really unclear to me when you would be in template code where
> you're not sure if you're working with an associative container or a
> sequential range.
>
> And that's ignoring that the equality for one isn't the equality for
> the other, as has been pointed out up-thread.
>
> No, this all just doesn't seem viable. ranges::contains is good enough
> for sequential searches for elements. If you need container-specific
> functionality, then you should know what the container is doing.
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
std::contains function. However, it's important to emphasize that this
function is specifically designed to simplify common coding tasks. While
containers and ranges serve distinct purposes, having a unified
std::contains function can greatly benefit developers by promoting code
consistency and simplifying template code that works with various data
structures.
The introduction of this function aligns with C++'s goal of providing
standard, intuitive solutions for everyday programming tasks. It offers the
flexibility to customize behavior when needed, making it a valuable
addition to the C++ standard library (akin to std::find).
Sincerely,
Robert
On Sun, Dec 24, 2023, 2:41 PM Jason McKesson via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> On Sun, Dec 24, 2023 at 12:25 PM Giuseppe D'Angelo via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> >
> > Il 24/12/23 14:50, Ville Voutilainen via Std-Proposals ha scritto:
> > > On Sun, 24 Dec 2023 at 15:44, Bjorn Reese via Std-Proposals
> > > <std-proposals_at_[hidden]> wrote:
> > >>
> > >> On 12/23/23 10:20, Robert Sitton via Std-Proposals wrote:
> > >>
> > >>> Function Signature:
> > >>> template <typename Container, typename T>
> > >>> bool std::contains(const Container& container, const T& value);
> > >>
> > >> Why does it deviate from all other standard algorithms that takes
> > >> iterators (or ranges for std::ranges algorithms)?
> > >
> > > Because it doesn't operate on iterators. If you pass a std::map to it,
> > > it'll call std::map::contains,
> > > it doesn't perform a silly linear walk from one iterator to another.
> > > What we're looking at here is basically
> > > "call the argument's contains() if available, do a ranges::contains
> otherwise".
> >
> > Indeed; see also std::erase/erase_if, although for them there isn't even
> > a way to do the "otherwise" part -- the container must offer its own
> > overload, which effectively makes them customization points.
> >
> > My 2 c,
>
> The difference here is that what the "erase" functions do
> *fundamentally* cannot be done on a range. Ranges are sequences of
> elements, but they do not have a way to structurally manipulate the
> sequence of elements. The *contents* of those elements, yes. The
> actual sequence, no. As such, the "erase" class of functions do what
> the `remove` functions do, but they also include the container
> operations that actually get those elements out of the sequence.
>
> This is why they rely on the existence of member functions.
>
> That is not really the case for `contains`. Well it is, but it's also not.
>
> Like with "erase", what "contains" might do depends on the container
> itself. But unlike "erase", there is some reasonable, conceptual
> default functionality: search through the container in sequence for
> the item.
>
> But there are problems even with that. Associative container
> "contains" doesn't necessarily work like sequential container
> "contains" functions. And this is true at the API level. A sequential
> container "contains" function looks for equality with an element. An
> associative container "contains" function looks for "equality" with a
> *key* (or some type comparable with a key), not the actual value type.
> So it's really unclear to me when you would be in template code where
> you're not sure if you're working with an associative container or a
> sequential range.
>
> And that's ignoring that the equality for one isn't the equality for
> the other, as has been pointed out up-thread.
>
> No, this all just doesn't seem viable. ranges::contains is good enough
> for sequential searches for elements. If you need container-specific
> functionality, then you should know what the container is doing.
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2024-01-02 21:46:19