Alexander Klauer
Alexander Klauer

Reputation: 1037

Formally correct way to explicitly call destructor of typedef'd class type

This question is related to: C++: Explicitly call destructor of template parameter's typedef

I have the following:

class A {
public:
  typedef std::shared_ptr<A> Ptr;
  …
};

Later on, I have a variable ptr of type A::Ptr * obtained via placement new, essentially by a call to a function like this:

A::Ptr * f(A::Ptr obj) {
  void * placement = get_legacy_storage(sizeof(obj));
  return new(placement) A::Ptr(obj);
}

I now want to undo the placement-new with an explicit destructor call. I do it like this:

ptr->A::Ptr::~Ptr();

As remarked in a comment to an answer to the linked question, this works on gcc, but not with clang. § 12.4p13 of the standard says

In an explicit destructor call, the destructor name appears as a ~ followed by a type-name or decltype-specifier that denotes the destructor's class type.

but I'm unsure how this interacts with typedefs and scope resolution. So, my questions are:

  1. What are the C++-11 standards-compliant ways of explicitly calling the destructor in the above situation (ideally without revealing the type of Ptr)?
  2. Do the answers for 1 work in gcc and/or clang? If not, what are the generally accepted workarounds?

Upvotes: 3

Views: 291

Answers (1)

Brian Bi
Brian Bi

Reputation: 119467

With the minimized example

struct A {};
struct B {
    using T = A;
};
int main() {
    A* a = new A;
    a->B::T::~T();
}

Godbolt indicates that Clang accepts the code as of version 11.

I'm not totally sure why Clang didn't accept this before, but perhaps it was related to a syntactic ambiguity which is discussed in more detail here.

The ambiguity is between

    postfix-expression . templateopt id-expression

and

    postfix-expression . pseudo-destructor-name

This ambiguity was resolved by P1131R2, and the resolution was voted as a DR; see CWG 2292. So I think that, even in C++11, the code should be considered valid.

Upvotes: 0

Related Questions