C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Bool casting operator to check if a container not empty

From: Edward Catmur <ecatmur_at_[hidden]>
Date: Thu, 2 Nov 2023 11:33:11 -0500
On Thu, 2 Nov 2023 at 11:23, Ville Voutilainen <ville.voutilainen_at_[hidden]>
wrote:

> On Thu, 2 Nov 2023 at 18:18, Edward Catmur <ecatmur_at_[hidden]> wrote:
> >> > I would dispute that; we use std::string_view() (i.e.
> std::string_view(nullptr, 0)) as a sentinel value, distinct from ""sv.
> Indeed, we would regard ""sv as truthy, since it is engaged in the sense
> that its data() is non-null. (The same holds for std::span, of course).
> >>
> >> How does that dispute anything?
> >>
> >> Do you write if (""sv) somewhere?
> >
> >
> > We write if (sv.data()) in some situations, and if (not sv.empty()) in
> others. The point is that there is no unambiguously best or most obvious
> property of a string_view for contextual conversion to bool.
>
> Thanks, that explains things.
>
> >> > If you really want contextual conversion to bool, wrap in a type that
> has that conversion. C++ is the land of zero-overhead, after all. And in
> generic code, use std::ranges::empty().
> >>
> >> Which doesn't work for non-ranges like pointers and optionals.
> >
> >
> > And you can't call std::ranges::begin() on those, so you need to wrap
> them in a range anyway if you want to pass them to generic code.
>
> No, I don't - because that generic code can separately deal with that
> difference.
>
> >> If
> >> there's an actual generic way to check that something has a value in
> >> it,
> >> be it singular or plural, you can write a generic check, and handle
> >> the singular/plural difference elsewhere, in slightly less generic
> >> generic
> >> code. ranges::empty() isn't that generic check.
> >
> >
> > If you're trying to distinguish between emptiness and containing
> one-or-more values, you must surely intend to access those values under the
> scope of that check
>
> No, I don't necessarily surely intend that, because that access may be
> elsewhere.
>
> >> The point of
> >> suggesting that containers could be bool-checked is that a contextual
> >> conversion
> >> to bool would be that generic check. We can certainly entertain having
> >> something else instead, but contextual conversions to bool are
> >> already idiomatic and common. We have them for iostreams, for example.
> >
> >
> > And that contextual conversion does *not* mean "contains a value", it
> means "is not in an error state", because for iostreams good() is the most
> relevant property in the majority of situations.
>
> Right, so it does mean "contains a value", because like a non-empty
> container, you can walk it and get values out of it.
>

Out of a std::ostream? I'd pay to watch that.

Indeed, a std::ostringstream can fail(), but still "contain a value" in the
sense that str() returns a non-empty string.

>> This is also not a zero-overhead question. If you don't need that
> >> check, don't use it. That causes no overhead for you. The ability to
> >> do such
> >> a check for a container has no space or time overhead for those who
> >> don't use it, so it conforms to any zero-overhead principle perfectly
> >> fine.
> > It means privileging 'not empty()' over all other properties that could
> be justifiably used for contextual conversion to bool. What of containers
> such as array that can't even be empty?
>
> What of them? We could easily give them a well-formed and well-defined
> emptiness query that is always false. I don't see how that's
> an obstacle of any kind.
>

And we do, which is fine for empty(), but to have a contextual conversion
to bool that is always true (or false, for a 0-sized array) would be a
source of confusion and frustration. Arthur's mentioned std::optional<bool>
and likewise std::array<bool, N> might be expected to evaluate all() or,
possibly, any() for contextual conversion to bool.

Received on 2023-11-02 16:33:24