Topic: Are there any proposals to extend static_pointer_cast to unique_ptr?


Author: jgottman@carolina.rr.com (Joe Gottman)
Date: Tue, 5 Jun 2007 01:40:10 GMT
Raw View
    std::shared_ptr defines three useful functions for doing explicit
casts on shared_ptr's: static_pointer_cast, dynamic_pointer_cast, and
const_pointer_cast.   Has anyone proposed extending these in the obvious
way to the new unique_ptr class?  I think this would be very useful,
especially in template code and when combined with the new auto syntax.

Joe Gottman

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Greg Herlihy <greghe@pacbell.net>
Date: Tue, 5 Jun 2007 00:46:07 CST
Raw View
On Jun 4, 6:40 pm, jgott...@carolina.rr.com (Joe Gottman) wrote:
>     std::shared_ptr defines three useful functions for doing explicit
> casts on shared_ptr's: static_pointer_cast, dynamic_pointer_cast, and
> const_pointer_cast.   Has anyone proposed extending these in the obvious
> way to the new unique_ptr class?  I think this would be very useful,
> especially in template code and when combined with the new auto syntax.

In what sort of expression would you envision using a
static_pointer_cast with a unique_ptr? Unlike a shared_ptr, a
unique_ptr is not copyable - so it is difficult for me to see how
static_pointer_cast() could be implemented for a unique_ptr in such a
way that static_pointer_cast() could not be used to make a copy of the
unique_ptr.

Granted, a unique_ptr may be "moved" to (or swapped with) another
unique_ptr - but to support both of those operations requires only a
suitably declared swap() routine and a move constructor for unique_ptr
- and not a cast operation upon the unique_ptr template class itself.

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Joe Gottman <jgottman@carolina.rr.com>
Date: Tue, 5 Jun 2007 10:07:51 CST
Raw View
Greg Herlihy wrote:
> On Jun 4, 6:40 pm, jgott...@carolina.rr.com (Joe Gottman) wrote:
>>     std::shared_ptr defines three useful functions for doing explicit
>> casts on shared_ptr's: static_pointer_cast, dynamic_pointer_cast, and
>> const_pointer_cast.   Has anyone proposed extending these in the obvious
>> way to the new unique_ptr class?  I think this would be very useful,
>> especially in template code and when combined with the new auto syntax.
>
> In what sort of expression would you envision using a
> static_pointer_cast with a unique_ptr? Unlike a shared_ptr, a
> unique_ptr is not copyable - so it is difficult for me to see how
> static_pointer_cast() could be implemented for a unique_ptr in such a
> way that static_pointer_cast() could not be used to make a copy of the
> unique_ptr.
>
> Granted, a unique_ptr may be "moved" to (or swapped with) another
> unique_ptr - but to support both of those operations requires only a
> suitably declared swap() routine and a move constructor for unique_ptr
> - and not a cast operation upon the unique_ptr template class itself.
>
> Greg

Suppose you have an object p of type unique_ptr<Base> and you know that
p.get() is of type Derived * (Base has a virtual destructor and Derived
inherits publicly from Base).  In that case, it is reasonable to want to
move p to a unique_ptr<Derived>.  Currently we can do this as
     unique_ptr<Derived> p2(static_cast<Derived *>(p.release()));
but this is verbose and slightly error-prone.  If you use p.get()
instead of p.release() the code still compiles but you later have a
double-delete and a crash.  If we instead declare a pair of
static_pointer_cast functions:

    // DON'T DEFINE THIS FUNCTION, JUST DECLARE IT
    template <class Dest, class Source>
    unique_ptr<Dest, Destructor>
    static_pointer_cast<Dest>(unique_ptr<Source> &p);


    template <class Dest, class Source>
    inline unique_ptr<Dest, Destructor>
    static_pointer_cast<Dest>(unique_ptr<Source> &&p)
    {
       return unique_ptr<Dest>(static_cast<Dest *>(p.release()));
    }

then users can just write
      unique_ptr<Derived> p2(move(p1));

and if they make the natural mistake of writing
      unique_ptr<Derived> p2(p1);

the result will be a link-time error as they call the first, undefined
function. Link-time errors are much better than compile-time errors
because they cannot be overlooked and their causes are more obvious.
Note that if the "Defaulted and Deleted Functions" proposal
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2210.html) is
accepted then we can declare the first function as a deleted function
and thus cause a compile-time error, which is even better than a
link-time error for focusing attention directly on the source of the error.

Joe Gottman

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]