2010-02-14

現状のshared_ptrの設計がまずい

// platform-specific handle type for resources.
typedef unsigned int handle_type ;

// platform-specific resource allocator and de-allocator function.
handle_type allocator() ;
void deallocator( handle_type handle ) ;

// user defined deleter.
struct handle_deleter
{
        typedef handle_deleter type ;
        typedef handle_type pointer ;

        void operator () ( handle_type handle ) const
        { deallocator( handle ) ; }
} ;

int main()
{
        // allocate a resource.
        // because of deleter, 
        // unique_ptr< handle_type, handle_deleter >::pointer is type of handle_type.
        // Not the handle_type *
        std::unique_ptr< handle_type, handle_deleter > handle( allocator() ) ;

        // move a resource to shared_ptr.
        // ill-fomed.
        // Because shared_ptr expects handle_type *.
        std::shared_ptr< handle_type > ptr( std::move(handle) ) ;
}

これはまずい。unique_ptrと違いすぎる。これでは、自前デリーターが使えない。

shared_ptrは、unique_ptrに合わせるべきではないだろうか。

しかしその場合、現行のshared_ptrにある、便利でType Erasureなデリーター指定が使えない。難しいものだ。

5 comments:

digitalghost said...

unique_ptr から shared_ptr へと所有の管理方法を変更することは、かなりレアケースだと思います。
普通 shared_ptr に移すことが分かっているのなら、最初から unique_ptr を使うことはないでしょう。

digitalghost said...

あ、ちょっと論点が間違ってました…
shared_ptr がそういうインターフェースになっているのには訳がありますから (http://www.ustream.tv/recorded/2981654)、現状のインターフェースのほうがよいと考えます。
その上で、例のような unique_ptr の使い方は、 shared_ptr でも を使うことを想定していないような使い方なので、これがうまくいかないのは仕方ないでしょう。

Egtra said...
This comment has been removed by the author.
Egtra said...

(<>がHTMLタグと認識されてしまったようなので投稿しなおします)もし、shared_ptrに手を加えるとしたら、現在template<typename T> class shared_ptr;のようになっているところをtemplate<typename T, typename PointerType = T*> class shared_ptr;とするのはどうでしょうか。上記の場合、std::unique_ptr< handle_type, handle_deleter >からstd::shared_ptr< handle_type, handle_type >へ変換可能とする(一般にremove_reference<D>::type::pointerからPointerTypeへ暗黙の変換が可能ならよしとする)のです。

江添亮 said...

それはジェネリックではありませんね。