Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Template alias destructor call

32 views
Skip to first unread message

Paavo Helde

unread,
Jan 22, 2020, 10:01:24 AM1/22/20
to
Please consider:

#include <new>

template <typename T, typename U>
class A {};

template <typename T>
using B = A<T, int>;

template <typename T>
void foo(B<T>* x) {
x->~B<T>(); // this line failing with clang
}

int main() {
alignas(sizeof(B<int>)) char buff[sizeof(B<int>)];
B<int>* p = new (buff) B<int>;
foo(p);
}

gcc and msvc compile this just fine. However, clang refuses:

test1.cpp:11:6: error: no member named 'B' in 'A<int, int>'
x->~B<T>();
^
test1.cpp:17:2: note: in instantiation of function template
specialization 'foo<int>' requested here
foo(p);
^
1 error generated.

Who is right? And if clang, then how to write an explicit B<T>
destructor call without relying on how B<T> happens to be defined?

Alf P. Steinbach

unread,
Jan 23, 2020, 5:26:20 AM1/23/20
to
C++17 §10.1.7.2/1 defines the /type-name/ after `~` as one of

class-name
enum-name
typedef-name
simple-template-id

This suggests that no matter how /simple-template-id/ turns out a fix
can be to use a /typedef-name/.

§17.2/1 defines /simple-template-id/ as (transcribed to typewriter-ish)

template-name `<` template-argument-list OPTIONAL `>`

The question is then whether your template alias `B` is a
/template-name/. The very same paragraph defines /template-name/
syntactically as

identifier

It then explains (in a non-normative note plus in normative text in
paragraph 3) that it's the name lookup that determines if a name is a
/template-name/. I fail to find that. However, §17.5.7 states that

An alias template is a name for a family of types. The name of the
alias template is a /template-name/.

So this is a bug in dang.

Workaround probably as mentioned above.

- Alf

Paavo Helde

unread,
Jan 23, 2020, 6:09:21 AM1/23/20
to
Thanks! The typedef workaround indeed seems to work:

template <typename T>
void foo(B<T>* x) {
typedef B<T> B_t;
x->~B_t();
}



Tim Rentsch

unread,
Jan 27, 2020, 4:40:09 AM1/27/20
to
Paavo Helde <myfir...@osa.pri.ee> writes:

> [problems with x->~B<T>().]
>
> Thanks! The typedef workaround indeed seems to work:
>
> template <typename T>
> void foo(B<T>* x) {
> typedef B<T> B_t;
> x->~B_t();
> }

Alternatively,

template <typename T>
void foo(B<T>* x) {
using B_t = B<T>;
x->~B_t();
}

Don't take this as a complaint, it is simply an unabashed plug
for choosing 'using' over 'typedef' (my own personal preference).
0 new messages