From: Joshua Lehrer on
I want to overload operator new on my class to take an additional
argument. I am therefore required to overload operator delete as well
so that if the constructor throws it will call the matching operator
delete.

I do not want to write additional class specific operator new/delete
that take no additional arguments.

My problem arises when I attempt to delete the pointer returned from
new. As I don't have a "default" operator delete on my class I need
to call the operator delete that takes parameters. The only way I can
find to do this is to call class::operator delete(pointer,args...);
However, this does not call the destructor. So, now I need to
explicitly call the destructor and then explicitly call
class::operator delete.

Is there a syntax to call delete which would pass arguments to the
operator delete after calling the destructor? I tried to match the
syntax of the call to new and that didn't work:

new(new_args) type(constructor_args);
delete(delete_args) pointer;

Any suggestions? Any explanation why the above doesn't work (other
than: the standard doesn't allow it). Why doesn't the standard allow
it?

e.g.:

#include <new>

struct foo {
//overload operator new
void* operator new(size_t, const char *) throw();

//corresponding operator delete to match
void operator delete(void *, const char *);

//constructor/destrucot
foo(int,int);
~foo();
};

void bar() {
foo * pfoo = new("hello") foo(1,2);

//no appropriate operator delete visible
// delete pfoo;

//syntax error
// delete("goodbye") pfoo;

//ugly
pfoo->~foo();
foo::operator delete(pfoo,"goodbye");
}

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Andy Venikov on
Joshua Lehrer wrote:
> I want to overload operator new on my class to take an additional
> argument. I am therefore required to overload operator delete as well
> so that if the constructor throws it will call the matching operator
> delete.
>
> I do not want to write additional class specific operator new/delete
> that take no additional arguments.
>
> My problem arises when I attempt to delete the pointer returned from
> new. As I don't have a "default" operator delete on my class I need
> to call the operator delete that takes parameters. The only way I can
> find to do this is to call class::operator delete(pointer,args...);
> However, this does not call the destructor. So, now I need to
> explicitly call the destructor and then explicitly call
> class::operator delete.
>
> Is there a syntax to call delete which would pass arguments to the
> operator delete after calling the destructor? I tried to match the
> syntax of the call to new and that didn't work:
>
> new(new_args) type(constructor_args);
> delete(delete_args) pointer;
>

Unfortunately, no.

Recently I had exactly the same question
(see "Why no placement delete?" dated Dec 3rd, 2009)
http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/196625d3468b9664/458b3f5c3a1b8828?#458b3f5c3a1b8828

The reasoning is vague. You can find the reasoning line on Bjarn's web-page:
<http://www2.research.att.com/~bs/bs_faq2.html#placement-delete>
'The reason that there is no built-in "placement delete" to
match placement new is that there is no general way of assuring
that it would be used correctly.'

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Dino on
Josh,

Why would you need to pass an argument to your delete call? Just to
invoke the correct delete function? I would think that at the time of
deletion the class should know how to properly clean itself up (even
if the delete was called because of an exception thrown in the
constructor).

I know you said that you did not want to "write additional class
specific operator new/delete that take no additional arguments" but I
think this is the way to go, and it can be done without too much
excess effort:


struct foo {
//overload operator new
void* operator new(size_t, const char *) throw();

//corresponding operator delete to match
void operator delete(void *, const char *);

void operator delete(void *);

//constructor/destrucot
foo(int,int);
~foo();

private:
void* operator new(size_t) throw();

};

Now your default operator new cannot be called, and doesn't need to be
implemented at all.

Meanwhile, define the non-default delete something like this:

void foo::operator delete(void * p, const char *) {
delete(p);
}

and define the default delete correctly.

Let me know what you think.

--Dino

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Joshua Lehrer on
On Feb 9, 8:16 pm, Dino <dinoch...(a)gmail.com> wrote:
> Josh,
>
> Why would you need to pass an argument to your delete call? Just to
> invoke the correct delete function? I would think that at the time of

There are a few reasons.

First, my question is one of consistency.

Why is this legal:

new(new_args) type;

but not this:

delete(delete_args) pointer;

especially when writing the new function for the former:

void* type::operator new(size_t, args...) throw();

requires you to write the support routine for the latter:

void type::operator delete(void *, args...);


Second, due to C++ lookup rules, writing a custom operator new now
requires you to not only write the proper matching operator delete,
but also to write a class specific generic operator delete. Why?
Because if you didn't, then a call to delete would fail to find a
matching overload. Name resolution would stop at the class level
where it finds the first operator delete, the args wouldn't match, and
it would fail to compile. So, now, one must write three routines, not
just one. :(


The reason I want to do it? I have a class than can be created in any
number of contexts. I want to be sure that it is created and
destroyed by the consumer in the same context. The context is an
argument to operator new and operator delete and, in debug mode, we
assert that the contexts match. You can think of a context as,
perhaps, a thread, and we want to assert that the object is created
and destroyed in the same thread context, with the thread being a
parameter to operators new and delete. (yes, I know, the operators
could lookup the current thread, that isn't the point).

Anyway, this being C++, I found other ways around my problem. I was
just curious why the parallel to calling new with arguments doesn't
exists for calling operator delete. I suspect this is one of those
areas where the answer is "because it wasn't in the original standard
and nobody has written a proposal to add it to the new standard."

-josh

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Goran on
On Feb 10, 2:16 am, Dino <dinoch...(a)gmail.com> wrote:
> Why would you need to pass an argument to your delete call? Just to
> invoke the correct delete function? I would think that at the time of
> deletion the class should know how to properly clean itself up (even
> if the delete was called because of an exception thrown in the
> constructor).

I would think not. If the ctor didn't finish, instance is not
constructed, meaning that's in a state it just should not be in. But
normally, e.g. destructor relies on class invariants that are
established by ctor(s), so dtor can easily fail to work properly.
Either that, either it has to take into account state variants that
stem from unfinished ctors. That's complexity I'd like to avoid. (Not
that this is a big problem in many-a-practical uses, but conceptually,
I think it is not a foundation to build a language on).

(Not related to Dino's post, but in general...)

I think that Andy and Joshua are missing the purpose of the overloaded
operator delete: it's __only__ purpose is to allow the compiler to
know what cleanup function it should call IF overloaded operator new
was called, BUT ctor blew up after that.

Once operator new + ctor went through, the case is either

1. normal operator delete must know all there is to know WRT freeing
memory __regardless___ of what overload of "operator new" was
initially used

or

2. dtor + specific memory-freeing function should be called. This is
what Joshua and Andy would like to be replaced by a call to an
overload of operator delete. But there are issues. Doing "delete
(params) p;" is really not much simpler. Code-size-wise, it's two
statements versus one - uh-oh, big deal. But most of the complexity
stems from the necessity to know what operator new was called for a
pointer we are about to "delete" - that one's the clincher, really.
That realistically can't be done automatically, so programmer must
work on it. Also e.g. smart pointers are out of question (that is,
they need approach 1).

All in all, what Joshua and Andy want would be additional feature with
a __really__ small benefit.

Goran.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]