Topic: Syntax for explicit call of destructor


Author: Niall Smart <njs3@doc.ic.ac.uk>
Date: 1998/05/31
Raw View
Hi,

I'm hoping someone with a copy of the FDIS can clarify this; unfortunately
I only have a copy of the December 96 draft.

Section 12.4 [class.dtor] point 12 describes the syntax used to explicitly
call a destructor of a class:

12In  an  explicit  destructor  call, the destructor name appears as a ~
  followed by a type-name that names the destructor's class  type.   The
  invocation  of  a  destructor is subject to the usual rules for member
  functions (_class.mfct_), that  is,  if  the  object  is  not  of  the
  destructor's class type and not of class derived from the destructor's
  class type, the program has undefined behavior (except  that  invoking
  delete on a null pointer has no effect).  [Example:
          struct B {
                  virtual ~B() { }
          };
          struct D : B {
                  ~D() { }
          };
          D D_object;
          typedef B B_alias;
          B* B_ptr = &D_object;
          D_object.B::~B();     // calls B's destructor
          B_ptr->~B();          // calls D's destructor
          B_ptr->~B_alias();    // calls D's destructor
          B_ptr->B_alias::~B(); // calls B's destructor
          B_ptr->B_alias::~B_alias(); // error, no B_alias in class B
   --end example]

This means that if I were writing a function which takes a pointer to
a T and destructs it then I should write it like this:

void destruct(T* t)
{
        t->~T();
}

and not:

void destruct(T* t)
{
        t->T::~T();
}

because this latter syntax is incorrect if T is a typedef for a class.  What
about scalar types though?  Section 5.2.4 [expr.pseudo] has this to say:

  5.2.4  Pseudo destructor call                            [expr.pseudo]

1 The use of a pseudo-destructor-name after a dot .  or arrow ->  opera-
  tor  represents  the  destructor for the non-class type named by type-
  name.  The result shall only be used as the operand for  the  function
  call  operator  (),  and the result of such a call has type void.  The
  only effect is the evaluation of the postfix-expression before the dot
  or arrow.

2 The  left  hand side of the dot operator shall be of scalar type.  The
  left hand side of the arrow operator shall be  of  pointer  to  scalar
  type.   This  scalar  type is the object type.  The type designated by
  the pseudo-destructor-name shall be the same as the object type.  Fur-
  thermore, the two type-names in a pseudo-destructor-name of the form
          ::opt nested-name-specifieropt type-name :: ~ type-name
  shall designate the same scalar type.

If I read this correctly then given:

typedef int I;
typedef int J;
typedef int K;

I* q;

all the following variants invoke the pseudo destructor for q:

        q->int::~int();
        q->I::~J();
        q->int::~K();

but these are syntax errors:

        q->~int();
        q->~I();

Therefore when writing my destruct function above, I have to know if T is a typedef
name for a class or scalar type to write it correctly:

for a scalar typedef:                   t->T::~T();
for a class typedef, or class name:     t->~T();

Is this correct?

Niall
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]