C++ invoke nested template class destructor
Asked Answered
S

1

7

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.

Soricine answered 18/2, 2014 at 8:18 Comment(1)
Consider x to be a member of a C struct, e.g. struct A { std::vector<int>::iterator x; ... } and you're given a struct A* to initialize and destroy. (In my case, it's a Python extension class instance.)Soricine
M
1

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.

Mixologist answered 18/2, 2014 at 8:29 Comment(3)
It is no destructor declaration, but a destructor call. (Your answer was better before). It's actually clang bug: llvm.org/bugs/show_bug.cgi?id=12350Baskett
@DieterLücking You're right. Please don't be like me.Mixologist
Or perhaps it's not a bug but clang detecting a C++ error no other compiler can see? bugzilla.mozilla.org/show_bug.cgi?id=623303Jacquelynnjacquenetta

© 2022 - 2024 — McMap. All rights reserved.