On Tue, Oct 17, 2017 at 11:30 AM, Arthur O'Dwyer
<
arthur....@gmail.com> wrote:
> Yes, this is accurate. The programmer should never expect "delete
> expressions" to work with objects that were not created via "new
> expressions".
Which programmer?
Suppose I have 10,000 programmers who make use of a particular
string-like class (as a matter of fact, I actually do.) There are only
a very few sources of this object, but plenty of consumers. It
currently uses no hanky-panky in allocation; therefore everyone
happily deletes them, stores them in unique_ptr, and so on. There is
X00 kLOC of code doing this. Now someone realizes that this class, on
a number of hot paths, would benefit from inlining allocation as in
the example. We can either rewrite every line of code, and train
every programmer to only use Destroy, and enforce use of
custom-deleter unique_ptrs, and ban every container that doesn't have
full support for that...or we can make "delete s" do the right thing.
As the paper points out, this is in fact already possible to do;
defining operator delete on the type works and is well-defined. But
it gives up efficiency in a sized-delete world.
> Sometimes the appropriate "glue factory" is "delete p", but it should be
> unsurprising that sometimes the appropriate "glue factory" is not "delete
> p".
I do not think this is an argument against making it possible to have
that deallocation function be "delete p" where we can.
> * The local choice of deallocation strategy leaks out to clients of the
> code.
> For example, a custom deleter must be specified when using unique_ptr<T>,
> and make_unique and make_shared can't be used any more.
>
> Note that the standard requires specializations of default_delete<T> to have
> the same effect as calling "delete p;", so specializing default_delete is
> not
> a correct alternative in C++17. We could lift that restriction, but that
> would
> not help for other (perhaps user-defined) resource management types that use
> new and delete to manage objects.
>
> The last bullet and its subsequent paragraph seem to hold two competing
> views of how-and-whether to extend C++. The bullet says, "We want to use
> 'delete' on factory-made pointers and have it Just Work. We must change the
> language to make that syntax work!" But the paragraph says, "You want to
> use 'default_delete' on factory-made pointers and have it Just Work? No,
> that would just complicate the language."
You may be misreading that section? We are saying that without P0722
or a similar fix, it is not possible to make default_delete work, as
overriding it would violate the spec. And while changing *that* rule,
instead of adding the feature we propose, would solve the problem for
std::unique_ptr<T> specifically, it would do nothing for all the
*other* possible users.
> Whereas my attitude is "You want to use anything other than the
> corresponding factory method to deallocate factory-made pointers and expect
> it to work? Just say no."
>
I think you are perhaps not seeing the proper perspective: we are
trying to widen the already large set of cases where "delete p" *is*
the appropriate factory deletion method. This is already an extremely
common pattern, and one with numerous advantages (the paper specifies
some of them.) Remember in particular that there are many reasons
where factory-creation is a useful pattern without any funny business
happening on the allocation (the trivial example being creation of an
object chosen dynamically from some virtual hierarchy.) Are you
saying that
Widget *Widget::Make(string widget_spec);
is badly designed unless I always also specify Widget::Destroy? (If
so, why do we have virtual destructors at all?) We simply want to be
able to use delete as our "factory deallocation method" in some
additional cases.