On 12/28/12, Jonathan Wakely <jwakely....@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