Lothar
Lothar

Reputation: 13067

How to explicitly call the destructor on a templated item member

The following code (paste to godbolt if you like) compiles

struct array {
    ~array();
};

struct node {
    array children;
};

void foo(node* bar) {
    bar->children.~array();
}

But if i use a template the compiler gets a syntax error when i explicitly reference the template type. Why and is there a working solution?

 #include <vector>
 struct node {
     std::vector<node> children;
 };

 void foo(node* bar) {
     bar->children.~std::vector<node>();
 }

Upvotes: 2

Views: 206

Answers (3)

Daniel Langr
Daniel Langr

Reputation: 23497

Starting from C++17, you can use std::destroy_at:

std::destroy_at(&bar->children);

Before C++17, such a function can be easily implemented manually (outside of the std namespace, of course) as:

template<class T>
void destroy_at(T* p) { p->~T(); }

The usage is IMHO much nicer then invoking destructor explicitly, which brings problems with namespaces. See, e.g., How to explicitly call a namespace-qualified destructor?.

Upvotes: 3

P.W
P.W

Reputation: 26800

As per [class.dtor]/14:

In an explicit destructor call, the destructor is specified by a ~ followed by a type-name or decltype-specifier that denotes the destructor’s class type.

So remove the std:: in the explicit call. However, explicit calling of a destructor is required only in certain cases such as using placement new to allocate memory. See this FAQ answer.

Upvotes: 0

paler123
paler123

Reputation: 976

Clang is more helpful with the error message: `

 <source>:7:20: error: '~' in destructor name should be after nested name specifier
 bar->children.~std::vector<node>();`

So basically you'll need to rely on ADL (I'm no guru, so maybe it's the wrong name for the stuff you use to make it work :) ) here, and call: bar->children.~vector<node>();

Upvotes: 4

Related Questions