unique_ptr's new static_assert check whether deleter can be invoked fails

Jonathan Wakely jwakely@redhat.com
Tue Sep 18 16:10:00 GMT 2018


On 17/09/18 16:41 +0100, Jonathan Wakely wrote:
>On 17/09/18 16:41 +0200, Stephan Bergmann wrote:
>>Compiling LibreOffice with recent GCC trunk, I came across an error 
>>like with this reproducer
>>
>>>$ cat test14.cc
>>>#include <memory>
>>>struct S1;
>>>struct S2;
>>>struct D { void operator ()(S1 *); };
>>>class C {
>>>   std::unique_ptr<S2, D> m;
>>>   C();
>>>   C(C const &);
>>>   ~C();
>>>   C & operator =(C const &);
>>>};
>>>
>>>$ gcc/inst/bin/g++ -c test14.cc
>>>In file included from /home/sbergman/gcc/inst/include/c++/9.0.0/memory:80,
>>>                from test14.cc:1:
>>>/home/sbergman/gcc/inst/include/c++/9.0.0/bits/unique_ptr.h: In instantiation of ‘class std::__uniq_ptr_impl<S2, D>’:
>>>/home/sbergman/gcc/inst/include/c++/9.0.0/bits/unique_ptr.h:172:33:   required from ‘class std::unique_ptr<S2, D>’
>>>test14.cc:6:28:   required from here
>>>/home/sbergman/gcc/inst/include/c++/9.0.0/bits/unique_ptr.h:145:22: error: static assertion failed: unique_ptr's deleter must be invocable with a pointer
>>>145 |       static_assert( __is_invocable<_Dp&, pointer&>::value,
>>>   |                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>>where S2 is an incomplete type, so the static_assert in unique_ptr 
>>(added recently with <https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=199f729ee3a6bd564151cda4caac289fbe7105cc> 
>>"Implement LWG 2905 changes to constrain unique_ptr constructors") 
>>can't determine that D can be invoked with an S2* (which it can if 
>>S2 is derived from S1).
>
>Oh dear, this is another example of the problem described in
>https://cplusplus.github.io/LWG/lwg-active.html#3099
>
>I think strictly speaking, your code is undefined according to
>[unique.ptr.single] p1. That requires the is_invocable condition to be
>true. I think that should be considered a defect in the standard, so
>I've requested a new issue to fix that.
>
>>I'm not sure whether this is a bug in LibreOffice (which would need 
>>to make sure S2 is a complete type when defining C),
>
>Or you can define D::pointer as S1* and then the assertion passes.
>
>struct D {
> using pointer = S1*;
> void operator ()(S1 *);
>};
>
>
>>or a too aggressive static_assert in libstdc++?
>
>Yes, I'll have to remove it.

I've committed the attached patch (and requested a new issue to fix
the standard). Thanks for bringing this to our attention.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch.txt
Type: text/x-patch
Size: 3865 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20180918/89211e10/attachment.bin>


More information about the Gcc-patches mailing list