C++ Logo

std-proposals

Advanced search

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

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Thu, 2 Nov 2023 12:55:04 -0400
On Thu, Nov 2, 2023 at 12:33 PM Edward Catmur via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> 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:
>>
> > 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.
>

Data point: If it compiled — which I'm glad it doesn't — I would expect `if
(array)` to return always-true, since that's what it does for C-style
arrays too (yes, even zero-sized ones, on compilers that support them).

Data point: If it compiled — which I'm glad it doesn't — I would expect `if
(bitset)` to mean the same thing as `if (bitset.any())`, since that's what
it does for bitmasks represented as integers. I certainly wouldn't *expect*
it to mean the same thing as `if (!std::ranges::empty(bitset))` i.e. `if
(bitset.size() != 0)`. (You might even be surprised that
std::ranges::empty works on a std::bitset, since a std::bitset is not a
range! *I* was surprised.)

Philosophy point: One might object that nobody's proposing to add boolean
conversions to *every* STL type (such as `array` and `bitset` and `path`);
the proposal was just to add boolean conversions to *some STL containers*
(like `vector` and `forward_list` and `map`). So we don't need to come up
with an overarching rule like "*bool(v) must be expression-equivalent to
std::ranges::empty(v) for any v under the sun*." No such *generic* rule is
even implementable in theory; C++ requires every type to physically provide
its own individual member `explicit operator bool() const`, and so the type
author must choose the semantics of that `operator bool` (whether it
returns .empty() or .any() or .has_value() or .get() or compares to null or
whatever). ...But that individualistic state of affairs is exactly the
status quo! The author of each STL container (*cough*Stepanov*cough*) have
already made that decision for their containers: that a container is
different from a bool. (If anyone should be expected to have a strong
opinion as to whether a sequence container is a kind of bool, it's
Stepanov! :))

–Arthur

Received on 2023-11-02 16:55:18