Не получается обернуть HANDLE в std::unique_ptr

35
03 декабря 2021, 07:20

Появилось желание обернуть в RAII классы ряд объектов из WinAPI (хендлы, сертификаты и т.д.) Самым очевидным решением оказались умные указатели, однако с ними возникла проблема следующего характера: deleter для них нельзя передавать в качестве параметра шаблона, нужно передавать в конструктор при создании, что очень неудобно в повседневном использовании, и не позволяет сделать alias (using unique_handle = std::unique_ptr<..>). Нашел на просторах интернета примитивное решение для HANDLE:

class SafeHandle
    : public std::unique_ptr<std::remove_pointer<HANDLE>::type,void(*)(HANDLE)>
{
  public:
    SafeHandle(HANDLE handle)
        : unique_ptr( handle, &SafeHandle::close )
    {
    }
    operator HANDLE()
    {
      return get();
    }
    const bool valid() const
    {
      return ( get() != INVALID_HANDLE_VALUE );
    }
  private:
    static void close( HANDLE handle )
    {
      if ( handle != INVALID_HANDLE_VALUE )
        CloseHandle( handle );
    }
};

Данный класс работает как ожидается, однако писать подобную обертку на каждый чих тоже крайне неудобно. Попробовал обобщить найденное решение через шаблоны следующим образом:

template <typename T>
class Unique
    : public std::unique_ptr<typename std::remove_pointer<T>::type, void(*)(T)>
{
  public:
      Unique(T res) 
      : std::unique_ptr<std::remove_pointer<T>>(res, &Unique::close)
    {
    }
    operator T()
    {
      return std::unique_ptr<std::remove_pointer<T>>::get();
    }
    const bool valid() const
    {
      return true; // Не имплементировал, планируется также передать через шаблон
    }
  private:
    static void close(T res)
    {
        // Здесь планируется сделать вызов функтора, передаваемого через шаблон
    }
};

При компиляции данного кода получаю 2 ошибки:

error C2512: 'std::unique_ptr<void,void (__cdecl *)(HANDLE)>::unique_ptr': no appropriate default constructor available
error C2614: 'Unique<HANDLE>': illegal member initialization: 'unique_ptr' is not a base or member

Данные ошибки недвусмысленно намекают, что проблема в наследовании, а именно, что происходит не вызов конструктора базового класса, а что-то другое. В первоначальном коде таких проблем не было, и я полагаю, что накосячил с шаблонами (не силен в них). Каким образом я могу достичь желаемого результата?

READ ALSO
Qt. Частичная перерисовка области

Qt. Частичная перерисовка области

У меня будет простое банковское приложениеИ я решил сделать такой интерфейс:

25
Получение доступа к объекту в приватном поле дружественного класса

Получение доступа к объекту в приватном поле дружественного класса

Есть класс, назовём его FirstclassВ нём, в приватном поле определён структурный тип следующего вида:

73
Сгенерировать N псевдослучайных чисел из диапазона [a;b)

Сгенерировать N псевдослучайных чисел из диапазона [a;b)

Есть ли в питоне/numpy аналог функции std::generate из C++? У меня есть функция без параметров, которая возвращает единственное значениеНадо создать...

26
LZ77. Функция сжатия

LZ77. Функция сжатия

Пишу курсовую, но никак не могу найти часть алгоритма сжатия LZ77

45