Reputation: 43
I know that a destructor in C++ does not return a value and its type cannot be explicitly specified.
However, I am wondering whether it can be considered an implicitly void
function and whether such a classification is correct according to the C++ standard.
I created a program where type of X destructor is void
.
#include <iostream>
#include <cxxabi.h>
using namespace std;
class X
{
};
int main()
{
X *x = new X();
char *fullname;
using destructor_type = decltype(x->~X());
const type_info &destructor_t = typeid(destructor_type);
fullname = abi::__cxa_demangle(destructor_t.name(), NULL, NULL, NULL);
cout << "[DESTRUCTOR] => " << destructor_t.name() << " => " << fullname << '\n';
free(fullname);
}
Can you explain to me how it is with destructor?
Upvotes: 4
Views: 122
Reputation: 72431
Note that the difference between an ordinary function's type and its return type. Given the declaration
double f(int);
the type of f
is double(int)
or "function of int
returning double
". The return type of f
is double
.
To be technically correct (the best kind of correct):
x->~X()
) has type void
.So,
struct X { ~X(); };
X x;
// Both are errors: Naming a destructor can only be done in
// a declaration or definition, or in a call expression with ().
// If they were valid, the destructor has no type anyway.
using T1 = decltype(X::~X);
using T2 = decltype(x.~X);
using T3 = decltype(x.~X());
static_assert(std::is_same_v<T3, void>); // OK
Note that sometimes decltype
gives the type from a name's declaration and sometimes it gives a type based on the type and value category of the expression. This is why decltype(a)
and decltype((a))
can be different things. But x.~X()
is not directly naming the destructor, so it falls into the category of just getting the expression type, not involving the declaration (explicit or implicit) of ~X
.
It's true a destructor is in many ways like a function with return type void
: You can use the statement return;
, you can't use return
with any actual value, and you can't get a value from an expression that calls it.
But there's one little difference showing that a destructor doesn't actually have return type void
: A function with return type void
can return
an expression that has type void
. A destructor can't return
any expression, even if it does have type void
.
void f();
void g(bool b) {
if (b)
return f(); // OK, returning void expression as void
else
return void(); // Strange but valid way of writing "return;"
}
Y::~Y() {
if (this->b)
return f(); // Error, can't put anything after "return"
else
return void(); // Error
}
Upvotes: 5