Date: Mon, 3 Jun 2019 09:23:05 -0400
On Sun, Jun 2, 2019 at 6:59 PM Zoe Carver <z.zoelec2_at_[hidden]> wrote:
> Thanks for the feedback, Arthur.
>
> > but it does suggest that maybe you've got an XY problem
> <http://xyproblem.info/> here.
> This is not an XY problem. I came up with this trait because I had to
> implement something similar in libc++ to fix an issue with overload
> resolution.
>
That seems like virtually the *definition* of an XY problem, doesn't it?
You had an unspecified "issue with overload resolution," and you did
something to work around it, and that something seemed to require an
is_deletable trait, and after maybe a couple more hops, we arrive at "the
STL should contain an is_deletable type trait out of the box; here's my
proposal." I'd be more interested in seeing the original X problem. Maybe
there's even a completely different (simpler) solution.
Or maybe your solution *is* the best and simplest one. But even then, you
should include the X problem in the proposal (or the email asking if there
should be a proposal), because that's your motivation section.
Your point about other unary operators in the standard library is a good
> one. Maybe they too should be added.
>
Not without motivation!
The language's and STL's asymmetric treatment of operators is a pet peeve
of mine. The core language permits operator+(A,B) and operator*(A) to be
non-member functions, but requires that operator[](A,B) be a member
function. The STL requires stateless callables all over the place, yet the
core language requires that the call operator, operator(), be a non-static
member function. The STL provides lifted metafunctions for operators
binary + - * / == != < <= > >= & | ^ && ||, unary !, unary -, and (as of
C++14) ~, but not unary + & * or binary << >> [] ().
However, your proposal seems like one place where the STL has remained
pretty consistent over the years: AFAIK, it never provides any type-traits
for detecting the well-formedness of a single operator. Adding a type-trait
std::is_deletable<T> would be *breaking* symmetry, not adding it.
> Do you have examples of
> There is at least one (but probably several) place(s) in the standard
> library where implementations must implement a trait like this. Here is an
> example struct where "is_array_deletable" is true and the other false:
>
> struct Foo
> {
> void operator delete[] (void* ptr) { free(ptr); }
> void operator delete (void* ptr) = delete;
> };
>
> It should not be hard to imagine the opposite.
>
I don't consider that an "example of real-world code." But for the sake of
argument, can you elaborate on what part of libc++ wants to detect `Foo`
and operate differently on it, and why?
–Arthur
> On Sun, Jun 2, 2019 at 11:08 AM Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
> wrote:
>
>> On Sun, Jun 2, 2019 at 1:00 PM Zoe Carver via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>>> Before submitting a proposal for the following type traits, I wanted to
>>> get the communities opinion. What are your thoughts on adding the following
>>> to the standard library?
>>>
>>>
>>> 1. is_deletable: if the expression "delete decltype<T>()" is
>>> well-formed, provides the member constant value equal to true.
>>> Otherwise, value is false.
>>>
>>>
>>> 2. is_array_deletable: if the expression "delete[] decltype<T>()" is
>>> well-formed, provides the member constant value equal to true. Otherwise,
>>> value is false.
>>>
>>>
>>> This should be a small feature with little-no impact. I have a sample
>>> implementation if that would be helpful.
>>>
>>
>> Those names do look like the right names for that particular facility.
>> But why do you want to add them to the standard library?
>> I mean, the standard library doesn't have is_negatable<T>, or
>> is_bitwise_negatable<T>, or has_sizeof<T>, or any of the other unary
>> operators that I can think of. So why should `delete` be special-cased?
>>
>> I would also caution that your proposal would make `is_deletable_v<int*>`
>> invariably true, even though not all `int*` values are in fact deletable.
>> Deletability is a dynamic, runtime, property of a pointer value. This isn't
>> a killer, but it does suggest that maybe you've got an XY problem
>> <http://xyproblem.info> here. A new type-trait may not be the right tool
>> for whatever underlying job you've actually got.
>>
>> Do you have examples of
>> (A) generic-programming contexts where an `is_deletable` facility would
>> have a beneficial effect?
>> (B) examples of real-world code where `is_deletable_v<T> && not
>> is_array_deletable_v<T>`, or vice versa?
>> (C) examples of real-world code where `is_deletable_v<T> && not
>> is_object_pointer_v<T>`, or vice versa?
>>
>> –Arthur
>>
>
> Thanks for the feedback, Arthur.
>
> > but it does suggest that maybe you've got an XY problem
> <http://xyproblem.info/> here.
> This is not an XY problem. I came up with this trait because I had to
> implement something similar in libc++ to fix an issue with overload
> resolution.
>
That seems like virtually the *definition* of an XY problem, doesn't it?
You had an unspecified "issue with overload resolution," and you did
something to work around it, and that something seemed to require an
is_deletable trait, and after maybe a couple more hops, we arrive at "the
STL should contain an is_deletable type trait out of the box; here's my
proposal." I'd be more interested in seeing the original X problem. Maybe
there's even a completely different (simpler) solution.
Or maybe your solution *is* the best and simplest one. But even then, you
should include the X problem in the proposal (or the email asking if there
should be a proposal), because that's your motivation section.
Your point about other unary operators in the standard library is a good
> one. Maybe they too should be added.
>
Not without motivation!
The language's and STL's asymmetric treatment of operators is a pet peeve
of mine. The core language permits operator+(A,B) and operator*(A) to be
non-member functions, but requires that operator[](A,B) be a member
function. The STL requires stateless callables all over the place, yet the
core language requires that the call operator, operator(), be a non-static
member function. The STL provides lifted metafunctions for operators
binary + - * / == != < <= > >= & | ^ && ||, unary !, unary -, and (as of
C++14) ~, but not unary + & * or binary << >> [] ().
However, your proposal seems like one place where the STL has remained
pretty consistent over the years: AFAIK, it never provides any type-traits
for detecting the well-formedness of a single operator. Adding a type-trait
std::is_deletable<T> would be *breaking* symmetry, not adding it.
> Do you have examples of
> There is at least one (but probably several) place(s) in the standard
> library where implementations must implement a trait like this. Here is an
> example struct where "is_array_deletable" is true and the other false:
>
> struct Foo
> {
> void operator delete[] (void* ptr) { free(ptr); }
> void operator delete (void* ptr) = delete;
> };
>
> It should not be hard to imagine the opposite.
>
I don't consider that an "example of real-world code." But for the sake of
argument, can you elaborate on what part of libc++ wants to detect `Foo`
and operate differently on it, and why?
–Arthur
> On Sun, Jun 2, 2019 at 11:08 AM Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
> wrote:
>
>> On Sun, Jun 2, 2019 at 1:00 PM Zoe Carver via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>>> Before submitting a proposal for the following type traits, I wanted to
>>> get the communities opinion. What are your thoughts on adding the following
>>> to the standard library?
>>>
>>>
>>> 1. is_deletable: if the expression "delete decltype<T>()" is
>>> well-formed, provides the member constant value equal to true.
>>> Otherwise, value is false.
>>>
>>>
>>> 2. is_array_deletable: if the expression "delete[] decltype<T>()" is
>>> well-formed, provides the member constant value equal to true. Otherwise,
>>> value is false.
>>>
>>>
>>> This should be a small feature with little-no impact. I have a sample
>>> implementation if that would be helpful.
>>>
>>
>> Those names do look like the right names for that particular facility.
>> But why do you want to add them to the standard library?
>> I mean, the standard library doesn't have is_negatable<T>, or
>> is_bitwise_negatable<T>, or has_sizeof<T>, or any of the other unary
>> operators that I can think of. So why should `delete` be special-cased?
>>
>> I would also caution that your proposal would make `is_deletable_v<int*>`
>> invariably true, even though not all `int*` values are in fact deletable.
>> Deletability is a dynamic, runtime, property of a pointer value. This isn't
>> a killer, but it does suggest that maybe you've got an XY problem
>> <http://xyproblem.info> here. A new type-trait may not be the right tool
>> for whatever underlying job you've actually got.
>>
>> Do you have examples of
>> (A) generic-programming contexts where an `is_deletable` facility would
>> have a beneficial effect?
>> (B) examples of real-world code where `is_deletable_v<T> && not
>> is_array_deletable_v<T>`, or vice versa?
>> (C) examples of real-world code where `is_deletable_v<T> && not
>> is_object_pointer_v<T>`, or vice versa?
>>
>> –Arthur
>>
>
Received on 2019-06-03 08:25:03