c++templatesdestructornested-class

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.


Solution

  • 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.