C++ Logo

std-proposals

Advanced search

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

From: Jonathan Wakely <cxx_at_[hidden]>
Date: Thu, 2 Nov 2023 17:06:38 +0000
On Thu, 2 Nov 2023 at 16:29, Chris Gary via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> Implicit conversions are the root of much evil in C++.
>>
> So is all the bikeshedding about primitives meant to protect misuse of
> what ultimately becomes a raw pointer.
> In this case, make that about what brand of styrene to use for a scale
> model bikeshed to be situated on a molehill.
> Its a trivial new addition. Use it or don't.
>

That's a terrible way to design a coherent standard library.



> Would it help users that follow this convention? Yes.
> Will it break existing code? No, since it isn't done with standard
> containers yet.
> Worried about running into code you don't like? Blog about it (no offense).
>
> I really wish more users would start learning with C, then treat this as
> "C with classes and a nifty type algebra".
>
> On Thu, Nov 2, 2023 at 9:59 AM Arthur O'Dwyer via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Ville, I think you've temporarily forgotten the mess that is
>> `optional<bool>`.
>> "Empty" (as in "it's a range of zero elements, i.e. its value is the
>> empty sequence") and "disengaged" (as in "it has no value") are two
>> different concepts; and both are fundamentally different from "falsey" (as
>> in "its value is boolean false").
>> Implicit conversions are the root of much evil in C++.
>>
>> On Thu, Nov 2, 2023 at 11:10 AM Ville Voutilainen via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>>>
>>> A call to an overload set that deals with ranges or singular values.
>>> Thus:
>>>
>>> template<class T, class F> void checked_process_it(T&& t)
>>> {
>>> if (t)
>>> process_it(std::forward<T>(t));
>>> else
>>> nag("hey, don't do that");
>>> }
>>>
>>
>> I think what the programmer meant here was more like:
>> if constexpr (!std::ranges::range<T>) {
>> process_it(std::views::single(std::forward<T>(t)));
>> } else {
>> process_it(t);
>> }
>> Obviously if `process_it` expects a ranges::range, it has to be prepared
>> to deal with the possibility that the range is empty (even if the way
>> it deals with that is just to say `if (ranges::empty(rg)) nag()`), since
>> ranges *can* be empty.
>> checked_process_it(std::vector<int>{}); // original code nags
>> checked_process_it(std::make_optional(std::vector<int>{})); //
>> original code fails to nag
>> Furthermore, if `checked_process_it` really intends to deal with
>> optionals, (smart) pointers, etc., then it is probably missing some code to
>> unwrap the optional/pointer after checking it for engagement/non-nullness.
>> That is, instead of
>> if (t)
>> process_it(t);
>> the programmer probably meant
>> if (t.has_value())
>> process_it(t.value()); // not just `t`!
>> and/or
>> if (t != nullptr)
>> process_it(*t); // not just `t`!
>>
>>
>> I can put it into a refined range concept that has the ability to
>>> check emptiness, though.
>>> And this really sounds like a bug in ranges that could be entertained
>>> to be fixed retroactively,
>>> even if that causes a little breakage. It's quite odd if a generic
>>> view that can be as lazy as imaginable
>>> can provide an empty() but a generic range can't.
>>>
>>
>> FYI, some input ranges can't provide .empty().
>> The C++20 Ranges library solution is to provide a* free function* (well,
>> CPO) `ranges::empty` and tell people to use it instead. Ranges provides all
>> these "generic" primitive functions through CPOs instead of member
>> functions; that's just its style, for better and worse.
>>
>> –Arthur
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2023-11-02 17:06:53