This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: unique_ptr's new static_assert check whether deleter can be invoked fails
- From: Jonathan Wakely <jwakely at redhat dot com>
- To: Stephan Bergmann <sbergman at redhat dot com>
- Cc: libstdc++ at gcc dot gnu dot org
- Date: Mon, 17 Sep 2018 16:41:38 +0100
- Subject: Re: unique_ptr's new static_assert check whether deleter can be invoked fails
- References: <f0849488-aea5-48da-5b1d-b53126761d2f@redhat.com>
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.