Topic: Calling dtor in a template class


Author: jamshid@ses.com (Jamshid Afshar)
Date: Mon, 22 Aug 1994 00:36:57 GMT
Raw View
Redirected to comp.std.c++.

In article <Cu8rv4.KD6@das.harvard.edu>,
Joshua Goodman <goodman@calliope.harvard.edu> wrote:
>In article <1994Aug2.205425.2779@camax.com> kotula@camax.com (Jeff Kotula) writes:
>> template<class T> void Array::resize() {
>>  ptr[i].~T();
>> [...]
>
>I ran into exactly this problem when I tried to create a resizable
>array class.  I assumed it was a compiler bug, until I checked the
>ARM.  (Someone else followed up to this message and said it was a
>compiler bug but without giving an ARM or other reference.)  I was not
>able to find any evidence in the ARM that it is a compiler bug.

Well, I was not able to find any evidence in the ARM that it isn't a
compiler bug. ;-)

Can you find anything in the grammar which would suggest that using a
template type argument T for an explicit destructor call is illegal,
while other uses such as `new T;' or `T::lessthan(x,y)' (from CPL2
8.4) are legal?

After all, it sure seems templates are the reason the notation for an
explicit destructor call is allowed for simple type names like int.
ARM 12.4: "Allowing [p->~int();] enables people to write code without
having to know if a destructor exists for a given type."

>template<class X> struct DestructorHack
>{
>    X x;
>    void operator delete(void *ptr) {} // Don't do anything!
>};
>
>#define DestroyAnything(ClassName, ObjectPointer) \
>    (delete (DestructorHack<ClassName *> *)ObjectPointer)
>
>This assumes that the memory layout for an object with no virtual
>functions and a single member of type X is exactly the same as the memory
>layout for an object of type X.  In general, this will be true.
>
>Note that this hack doesn't work for abstract types, but then you
>can't have an array of abstract types, so that that is OK.

The hack also doesn't work for types without a default constructor,
and the ability to make arrays out of objects without a default
constructor is one of the reasons I defined my own Array class
template.  On the other hand, I believe Standard C++ will probably
continue to (implicitly) require that for:

 struct H { X x; };
 H h;

(void*)&h == &h.x.  So, the only gripe the ARM would have with your
hack is that "The effect of applying delete to a pointer not obtained
from the new operator without a placement specification is undefined
and usually harmful".  But I doubt even interpreted C++ environments
would flag an error since memory checking is usually done at a
lower-level.

Since your technique is easier than writing lots of `destroy(T& t)'
function template specializations, and since it's only a hack to
workaround compiler bugs, I would certainly recommend it to anyone
whose compiler does not allow `ptr->~T();'.

Jamshid Afshar
jamshid@ses.com