Date: Wed, 27 Sep 2023 19:34:29 -0600
Sorry, need to fix an actual compilation error in that last example:
https://godbolt.org/z/5fjfvzbn3
Recap: What did std::partial_ordering do for me above to help structure the
rest of the predicate so that it works as implied?
On Wed, Sep 27, 2023 at 7:29 PM Chris Gary <cgary512_at_[hidden]> wrote:
> Though it's interesting that you're suddenly OK with including a
>> header for your `std::saturate_to_tbl` function. You *are* proposing
>> adding such a function to the standard library, right? Because your
>> proposal is incomplete without it, as it would be unable to interact
>> with C convention-based code. Unlike the status quo, where all you
>> have to do is apply `<=> 0`.
>>
>
> I kept saying the likes of "saturate_to_tbl" are supposed to be
> compiler-generated code.
>
> What is the equivalent of:
>
> auto operator <=> ( const Example &other ) const noexcept
> { return this->value <=> other.value; }
>
> and not having to resort to writing any of the other 6?
>
> This works as it reads:
> https://godbolt.org/z/7xfKrKfTb
>
> This is confusing:
> https://godbolt.org/z/WjGExfxeW
>
> This is very confusing (re-done to use partial_ordering, not that it
> matters):
> https://godbolt.org/z/1xfcjacse
>
> Even the documentation states "object that can be compared against 0".
> Before I suggested the interval saturation, that is what I was expecting.
> Someone brought up NaNs, so the table-lookup was just another exposition of
> making that odd idea work.
>
> Are you expecting a thing to behave a certain way in a container? Write a
> predicate for the container.
>
> Trying to convey the ordering category of a type? There are static
> solutions (a return type), and there are dynamic solutions.
> An enum here doesn't help where the category may change dynamically.
> So, what I've tried to do is just use std::partial_ordering, and cope. As
> demonstrated above, that can't happen in a simple way apparently.
>
> Using the most general category is no different than using an int, but
> back to the point above: Where is the advantage of the rich enum type if a
> single <=> in the most general case, even a trivial one, does not behave as
> intuition suggests?
>
> On Wed, Sep 27, 2023 at 7:13 PM Jason McKesson via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> On Wed, Sep 27, 2023 at 7:45 PM Chris Gary via Std-Proposals
>> <std-proposals_at_[hidden]> wrote:
>> >>
>> >> You've repeated yourself without thinking about what I wrote. You've
>> answered
>> >> for equality. Now think about the other operators: how does it
>> implement "is
>> >> less" for the type I proposed earlier? Mind you, it is strongly
>> ordered and
>> >> memcmp() only returns sign, not constraining itself to -1, 0, 1.
>> >
>> >
>> > What I've stated covers all cases of <=>. I keep repeating myself
>> because I keep reading the same appeal to convention over and over again.
>> >
>> > The issues of composability that keep coming up are the same as the
>> distinction in byte ordering. LE integers compose regardless of limb size,
>> BE do not. For an LE thing made out of smaller BE things, value comparisons
>> are needed and so on.
>> >
>> > Memberwise comparison is already implemented in exactly the same way as
>> I've described.
>> > Its even in the documentation:
>> >>
>> >> Defaulted three-way comparison
>> >>
>> >> The default operator<=> performs lexicographical comparison by
>> successively comparing the base (left-to-right depth-first) and then
>> non-static member (in declaration order) subobjects of T to compute <=>,
>> recursively expanding array members (in order of increasing subscript), and
>> stopping early when a not-equal result is found, that is:
>> >
>> >
>> > https://godbolt.org/z/7xfKrKfTb
>> >
>> > The same as memberwise assignment, default construction, etc...
>> > Takes the least restrictive ordering, or partial_order.
>> > It looks like all things are in general partial_order, if that helps
>> clarify again.
>> >
>> > saturate_to_tbl() -> {-1,0,1}|{-2}. You can call the members whatever
>> you'd like. Everything not {a,b,c} is an error and maps to "explode",
>> "idunno", or "hot_potato".
>> > I don't advise building general predicates on the de-facto definition
>> of memcmp.
>>
>> But that is *exactly* what people will do. All you've done is
>> introduce fragility to the system, where `int` in one place doesn't
>> really mean `int`.
>>
>> There is a *very* long-standing convention in C code for 3-way
>> comparison functions to return a signed integer where the sign
>> represents the directionality of the comparison. And I'm not just
>> talking about the standard C library functions like `memcmp` and
>> `strlen`. Pretty much any 3-way comparison function that returns an
>> `int` *does not* require that the integer is on the range [-1, 1]. All
>> values are valid, and the only thing you're expected to test is the
>> sign (or zero).
>>
>> C++ explicitly didn't want to engage with this convention for its
>> 3-way comparison operator. So they created a *new* convention: the
>> ordering types. It's a convention that gives you a *compile error* if
>> you try to directly return the result of `memcmp`, but if you return
>> `memcmp(...) <=> 0`, it works fine.
>>
>> That's what good design looks like: noisy errors when you do it wrong,
>> and easy to do it right.
>>
>> You are trying to invent your *own* convention and crowbar it into
>> C++. A convention that is syntactically identical to the established C
>> convention, but is semantically incompatible with it. And because of
>> that, there is no compile-time test to know whether you're using the
>> C-convention or the Chris-convention. You can do it wrong and get
>> silently working code... until someone does the wrong thing and it
>> doesn't work anymore.
>>
>> That's what bad design looks like: errors are allowed to creep into
>> code and make it appear to work... until it doesn't, and with few
>> pointers to where things went wrong.
>>
>> Though it's interesting that you're suddenly OK with including a
>> header for your `std::saturate_to_tbl` function. You *are* proposing
>> adding such a function to the standard library, right? Because your
>> proposal is incomplete without it, as it would be unable to interact
>> with C convention-based code. Unlike the status quo, where all you
>> have to do is apply `<=> 0`.
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>
https://godbolt.org/z/5fjfvzbn3
Recap: What did std::partial_ordering do for me above to help structure the
rest of the predicate so that it works as implied?
On Wed, Sep 27, 2023 at 7:29 PM Chris Gary <cgary512_at_[hidden]> wrote:
> Though it's interesting that you're suddenly OK with including a
>> header for your `std::saturate_to_tbl` function. You *are* proposing
>> adding such a function to the standard library, right? Because your
>> proposal is incomplete without it, as it would be unable to interact
>> with C convention-based code. Unlike the status quo, where all you
>> have to do is apply `<=> 0`.
>>
>
> I kept saying the likes of "saturate_to_tbl" are supposed to be
> compiler-generated code.
>
> What is the equivalent of:
>
> auto operator <=> ( const Example &other ) const noexcept
> { return this->value <=> other.value; }
>
> and not having to resort to writing any of the other 6?
>
> This works as it reads:
> https://godbolt.org/z/7xfKrKfTb
>
> This is confusing:
> https://godbolt.org/z/WjGExfxeW
>
> This is very confusing (re-done to use partial_ordering, not that it
> matters):
> https://godbolt.org/z/1xfcjacse
>
> Even the documentation states "object that can be compared against 0".
> Before I suggested the interval saturation, that is what I was expecting.
> Someone brought up NaNs, so the table-lookup was just another exposition of
> making that odd idea work.
>
> Are you expecting a thing to behave a certain way in a container? Write a
> predicate for the container.
>
> Trying to convey the ordering category of a type? There are static
> solutions (a return type), and there are dynamic solutions.
> An enum here doesn't help where the category may change dynamically.
> So, what I've tried to do is just use std::partial_ordering, and cope. As
> demonstrated above, that can't happen in a simple way apparently.
>
> Using the most general category is no different than using an int, but
> back to the point above: Where is the advantage of the rich enum type if a
> single <=> in the most general case, even a trivial one, does not behave as
> intuition suggests?
>
> On Wed, Sep 27, 2023 at 7:13 PM Jason McKesson via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> On Wed, Sep 27, 2023 at 7:45 PM Chris Gary via Std-Proposals
>> <std-proposals_at_[hidden]> wrote:
>> >>
>> >> You've repeated yourself without thinking about what I wrote. You've
>> answered
>> >> for equality. Now think about the other operators: how does it
>> implement "is
>> >> less" for the type I proposed earlier? Mind you, it is strongly
>> ordered and
>> >> memcmp() only returns sign, not constraining itself to -1, 0, 1.
>> >
>> >
>> > What I've stated covers all cases of <=>. I keep repeating myself
>> because I keep reading the same appeal to convention over and over again.
>> >
>> > The issues of composability that keep coming up are the same as the
>> distinction in byte ordering. LE integers compose regardless of limb size,
>> BE do not. For an LE thing made out of smaller BE things, value comparisons
>> are needed and so on.
>> >
>> > Memberwise comparison is already implemented in exactly the same way as
>> I've described.
>> > Its even in the documentation:
>> >>
>> >> Defaulted three-way comparison
>> >>
>> >> The default operator<=> performs lexicographical comparison by
>> successively comparing the base (left-to-right depth-first) and then
>> non-static member (in declaration order) subobjects of T to compute <=>,
>> recursively expanding array members (in order of increasing subscript), and
>> stopping early when a not-equal result is found, that is:
>> >
>> >
>> > https://godbolt.org/z/7xfKrKfTb
>> >
>> > The same as memberwise assignment, default construction, etc...
>> > Takes the least restrictive ordering, or partial_order.
>> > It looks like all things are in general partial_order, if that helps
>> clarify again.
>> >
>> > saturate_to_tbl() -> {-1,0,1}|{-2}. You can call the members whatever
>> you'd like. Everything not {a,b,c} is an error and maps to "explode",
>> "idunno", or "hot_potato".
>> > I don't advise building general predicates on the de-facto definition
>> of memcmp.
>>
>> But that is *exactly* what people will do. All you've done is
>> introduce fragility to the system, where `int` in one place doesn't
>> really mean `int`.
>>
>> There is a *very* long-standing convention in C code for 3-way
>> comparison functions to return a signed integer where the sign
>> represents the directionality of the comparison. And I'm not just
>> talking about the standard C library functions like `memcmp` and
>> `strlen`. Pretty much any 3-way comparison function that returns an
>> `int` *does not* require that the integer is on the range [-1, 1]. All
>> values are valid, and the only thing you're expected to test is the
>> sign (or zero).
>>
>> C++ explicitly didn't want to engage with this convention for its
>> 3-way comparison operator. So they created a *new* convention: the
>> ordering types. It's a convention that gives you a *compile error* if
>> you try to directly return the result of `memcmp`, but if you return
>> `memcmp(...) <=> 0`, it works fine.
>>
>> That's what good design looks like: noisy errors when you do it wrong,
>> and easy to do it right.
>>
>> You are trying to invent your *own* convention and crowbar it into
>> C++. A convention that is syntactically identical to the established C
>> convention, but is semantically incompatible with it. And because of
>> that, there is no compile-time test to know whether you're using the
>> C-convention or the Chris-convention. You can do it wrong and get
>> silently working code... until someone does the wrong thing and it
>> doesn't work anymore.
>>
>> That's what bad design looks like: errors are allowed to creep into
>> code and make it appear to work... until it doesn't, and with few
>> pointers to where things went wrong.
>>
>> Though it's interesting that you're suddenly OK with including a
>> header for your `std::saturate_to_tbl` function. You *are* proposing
>> adding such a function to the standard library, right? Because your
>> proposal is incomplete without it, as it would be unable to interact
>> with C convention-based code. Unlike the status quo, where all you
>> have to do is apply `<=> 0`.
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>
Received on 2023-09-28 01:34:41