Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #71515 > unrolled thread

Template alias destructor call

Started byPaavo Helde <myfirstname@osa.pri.ee>
First post2020-01-22 17:01 +0200
Last post2020-01-27 01:40 -0800
Articles 4 — 3 participants

Back to article view | Back to comp.lang.c++


Contents

  Template alias destructor call Paavo Helde <myfirstname@osa.pri.ee> - 2020-01-22 17:01 +0200
    Re: Template alias destructor call "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2020-01-23 11:26 +0100
      Re: Template alias destructor call Paavo Helde <myfirstname@osa.pri.ee> - 2020-01-23 13:09 +0200
        Re: Template alias destructor call Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-01-27 01:40 -0800

#71515 — Template alias destructor call

FromPaavo Helde <myfirstname@osa.pri.ee>
Date2020-01-22 17:01 +0200
SubjectTemplate alias destructor call
Message-ID<r09o3o$a96$1@dont-email.me>
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?

[toc] | [next] | [standalone]


#71530

From"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>
Date2020-01-23 11:26 +0100
Message-ID<r0bsc1$jsa$1@dont-email.me>
In reply to#71515
On 22.01.2020 16:01, Paavo Helde wrote:
> 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?

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

[toc] | [prev] | [next] | [standalone]


#71531

FromPaavo Helde <myfirstname@osa.pri.ee>
Date2020-01-23 13:09 +0200
Message-ID<r0busk$24i$1@dont-email.me>
In reply to#71530
On 23.01.2020 12:26, Alf P. Steinbach wrote:
> On 22.01.2020 16:01, Paavo Helde wrote:
>> 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?
>
> 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.

Thanks! The typedef workaround indeed seems to work:

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


[toc] | [prev] | [next] | [standalone]


#71618

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2020-01-27 01:40 -0800
Message-ID<86zhe9grv3.fsf@linuxsc.com>
In reply to#71531
Paavo Helde <myfirstname@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).

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web