This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: [patch] std::unique_ptr<T[], D> improvements
- From: Lawrence Crowl <crowl at googlers dot com>
- To: Jonathan Wakely <jwakely dot gcc at gmail dot com>
- Cc: "libstdc++" <libstdc++ at gcc dot gnu dot org>, gcc-patches <gcc-patches at gcc dot gnu dot org>, Geoffrey Romer <gromer at google dot com>
- Date: Tue, 1 Jan 2013 12:40:39 -0800
- Subject: Re: [patch] std::unique_ptr<T[], D> improvements
- References: <CAH6eHdQCP8DLv35YtXr-QpMtkWUe+p6ryL0h4PwBZa2K0q+NEg@mail.gmail.com> <CAGqM8fYj0wgzjVpAE8NxX2rPJYZ4nVc7hcr0nphW8sFy0D6R7A@mail.gmail.com> <CAH6eHdRSTFr9RSEfCwzgCM1YoqD=2sX6ESkwg4rTOUX5cjJVLg@mail.gmail.com>
On 12/28/12, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
> On 28 December 2012 01:51, Lawrence Crowl wrote:
>> I'm not getting errors when converting from derived to base.
>> E.g. the following compiles, when it should not.
>>
>> std::unique_ptr<const base []> acb_ad(new derived[3]);
>
> I get an error:
>
> shm$ cat up.cc
> #include <memory>
> struct base { };
> struct derived : base { virtual ~derived() = default; };
> std::unique_ptr<const base []> acb_ad(new derived[3]);
> shm$
> shm$ g++11 up.cc -c
> up.cc:4:53: error: use of deleted function ‘std::unique_ptr<_Tp [],
> _Dp>::unique_ptr(_Up*) [with _Up = derived; <template-parameter-2-2> =
> void; _Tp = const base; _Dp = std::default_delete<const base []>]’
> std::unique_ptr<const base []> acb_ad(new derived[3]);
> ^
> In file included from /home/redi/gcc/4.x/include/c++/4.8.0/memory:81:0,
> from up.cc:1:
> /home/redi/gcc/4.x/include/c++/4.8.0/bits/unique_ptr.h:343:2: error:
> declared here
> unique_ptr(_Up* __p) = delete;
> ^
That was pilot error on my part. However, I've been having trouble
when the argument to the constructor or reset has a conversion
operator. The code does distinquish between a safe conversion to
base and an unsafe conversion to derived.
Here is a simplified version of the problem. The code as is fails
to reject the last two calls to accept. The primary reason is that
is_convertable permits both the invocation of the conversion operator
and the derived to base conversion. At present, I see no way to
get a handle on the 'natural' return type of the conversion operator.
#include <type_traits>
struct base { };
struct derived : base { };
template <typename T, typename F>
typename std::enable_if<
std::is_convertible< F, T* >::value,
T*
>::type
accept(F arg) { return arg; }
template <typename T, typename F>
typename std::enable_if<
!std::is_convertible< F(*)[], T(*)[] >::value,
T*
>::type
accept(F* arg) = delete;
struct cvt_b {
operator base*() { return 0; }
};
struct cvt_d {
operator derived*() { return 0; }
};
int main()
{
// should PASS
accept< base >( (base*)0 );
accept< const base >( (base*)0 );
accept< base >( cvt_b() );
accept< const base >( cvt_b() );
// should FAIL
accept< base >( (derived*)0 );
accept< const base >( (derived*)0 );
accept< base >( cvt_d() );
accept< const base >( cvt_d() );
}
--
Lawrence Crowl