обрабатывать управление с boost :: shared_ptr <> - PullRequest
0 голосов
/ 11 августа 2010

Я хотел бы использовать boost :: shared_ptr <> для инкапсуляции управления временем жизни дескриптора.Мой дескриптор и его функции создания / уничтожения объявлены следующим образом:

typedef const struct MYHANDLE__ FAR* MYHANDLE;

void CloseMyHandle( MYHANDLE );
MYHANDLE CreateMyHandle();

В идеале, я бы хотел использовать boost::shared_ptr<> для управления дескриптором вот так:, поскольку дескриптор объявлен как const struct * вместо обычного void *, я получаю такие ошибки:

boost/smart_ptr/shared_ptr.hpp(199) : error C2440: 'initializing' : cannot convert from 'const MYHANDLE__ *' to 'void *'

Я могу использовать функтор для приведения void * к MYHANDLEкак это:

struct DeallocateMyHandle
{ 
    void operator()( void* handle )
    {
        CloseMyHandle( ( MYHANDLE )handle ); 
    };
};

boost::shared_ptr< void > my_handle( ( void* )CreateMyHandle(), DeallocateMyHandle() );

Но я бы предпочел иметь метод, который не использует отдельный функтор.Есть ли способ сделать это только в конструкторе boost::shared_ptr<>, который я не вижу?Или я застрял с функтором?

Спасибо, PaulH

Ответы [ 3 ]

4 голосов
/ 11 августа 2010

Почему бы не использовать:

boost::shared_ptr< const MYHANDLE__ > my_handle( CreateMyHandle(), &CloseMyHandle );

PS. Обратите внимание, что использование двойного подчеркивания не допускается (оно зарезервировано для реализации).
См .: Правила об идентификаторах

2 голосов
/ 24 августа 2011

Если HANDLE является общедоступным типом, но тип, на который он указывает, не является, существует очень простой способ написать это:

template <typename T> struct unpointer { };
template <typename T> struct unpointer<T*> { typedef T type; };
boost::shared_ptr<typename unpointer<MYHANDLE>::type> my_handle(
  CreateMyHandle(), &CloseMyHandle);

(Если вы используете действительно старую версию VC ++ илиgcc вы, вероятно, должны опустить "typename" там.)

Конечно, это становится немного многословным и утомительным.Если у вас есть только один тип дескриптора, вы, вероятно, напишите это:

typedef typename unpointer<MYHANDLE>::type MYHANDLEREF;
typedef boost::shared_ptr<MYHANDLEREF> my_shared_ptr;

Если у вас есть все виды дескрипторов для переноса (и так как похоже, что вы делаете Win32API, вы, вероятно, делаете), создайте шаблон, который упаковывает вещи на любом уровне, который вы предпочитаете (шаблон класса, который просто генерирует типы, handle_ptr<T>, который подклассов shared_ptr<unpointer<T>> и добавляет удаленный по умолчанию для вас, handle_ref<T> который использует shared_ptr за кулисами, чтобы имитировать MYHANDLE & вместо того, чтобы имитировать то, на что MYHANDLE указывает, и т. д.)

0 голосов
/ 11 августа 2010

Ваш тип shared_ptr должен быть таким:

boost::shared_ptr< const MYHANDLE__ FAR>

Таким образом, когда shared_ptr делает из него указатель, он становится:

const MYHANDLE__ FAR*

Что соответствует вашемуMYHANDLE введите точно:

#include <boost/shared_ptr.hpp>

struct MYHANDLE__ {};
typedef const MYHANDLE__* MYHANDLE;

void CloseMyHandle(MYHANDLE) {}
MYHANDLE CreateMyHandle(void) { return 0; }

int main()
{
    typedef boost::shared_ptr<const MYHANDLE__> ptr_type;
    ptr_type my_handle( CreateMyHandle(), &CloseMyHandle );
}

Обратите внимание, я действительно сомневаюсь, что вам нужно FAR, это из 16-битного возраста.Он расширяется до far или ничего, в зависимости от того, что вы компилируете для 16-битной системы (подсказка: вы не компилируете для 16-битной версии. :)).Насколько я знаю, far даже больше не является расширением.

Кроме того, как сказал Мартин, нигде не используйте двойные подчеркивания.

...