Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ invoke nested template class destructor

Suppose I have a variable x of type std::vector::iterator that was allocated (for other reasons) with placement new, e.g.

new((void*)&x) std::vector<int>::iterator();

How does one call its destructor in a standards compliant way? Doing

x.std::vector<int>::iterator::~iterator();

for example works in gcc but not clang.

like image 567
robertwb Avatar asked Feb 18 '14 08:02

robertwb


People also ask

How do you call a destructor from a non class?

In generic contexts, the destructor call syntax can be used with an object of non-class type; this is known as pseudo-destructor call: see member access operator . A class may have one or more prospective destructors, one of which is selected as the the destructor for the class.

Are destructors noexcept in C++?

In practice, implicit destructors are noexcept unless the class is "poisoned" by a base or member whose destructor is noexcept (false) . The implicitly-declared or defaulted destructor for class T is undefined (until C++11)defined as deleted (since C++11) if any of the following is true:

What is the use of destructor in C?

In C#, destructor (finalizer) is used to destroy objects of class when the scope of an object ends. It has the same name as the class and starts with a tilde ~. For example, class Test { ... //destructor ~Test () { ...

What is a destructor in the NET Framework?

The Destructor is called implicitly by the .NET Framework’s Garbage collector and therefore programmer has no control as when to invoke the destructor. An instance variable or an object is eligible for destruction when it is no longer reachable. A Destructor is unique to its class i.e. there cannot be more than one destructor in a class.


1 Answers

All standard (and standard-compliant) iterators follow the Iterator concept, which is required to be Destructible. Thus, it suffice to simply call the iterator's destructor just as you would in any other (non-trivial) types constructed with placement new.

x.~iterator_type();   // where x is an iterator

Note that if you refer to the iterator through a pointer, you must use the -> operator:

#include <vector>


int main() {
    auto buffer = new char[sizeof(std::vector<int>::iterator)];

    auto iterator = new((void*)buffer) std::vector<int>::iterator();
    iterator->std::vector<int>::iterator::~iterator();

    delete[] buffer;
}

LIVE EXAMPLE (GCC)

UPDATE: It seems that Clang has some problems compiling the (I presume standards-compliant) code. You can make a work-around on this by providing an indirection when calling the destructor:

#include <vector>

template<typename T>
void call_destructor(T* x) {
    x->~T();
}

int main() {
    auto buffer = new char[sizeof(std::vector<int>::iterator)];

    auto iterator = new((void*)buffer) std::vector<int>::iterator();
    //iterator->std::vector<int>::iterator::~iterator();
    call_destructor(iterator);

    delete[] buffer;
}

LIVE EXAMPLE (clang)

UPDATE: Yah. It's a bug in clang: http://llvm.org/bugs/show_bug.cgi?id=12350. See Dieter Lücking's comment.


I'm very sorry to all of you, especially to the OP, for this mess.

like image 128
Mark Garcia Avatar answered Oct 12 '22 11:10

Mark Garcia