On Sun, Jun 2, 2019 at 6:59 PM Zoe Carver <z.zoelec2@gmail.com> wrote:
Thanks for the feedback, Arthur. 

> but it does suggest that maybe you've got an XY problem 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@gmail.com> wrote:
On Sun, Jun 2, 2019 at 1:00 PM Zoe Carver via Std-Proposals <std-proposals@lists.isocpp.org> 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 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