RAII для WinAPI с учетом 64-битной архитектуры Windows

139
13 июня 2019, 22:40

Постепенно мигрирую с C на C++ и 32- на 64-битную Windows. При написании программ с использованием WinAPI возник ряд вопросов, объединенных одной общей темой - RAII. Так как я изучаю C++ всего третий месяц, а понять некоторые тонкости вышеозвученной идиомы программирования все же хотелось уже сейчас (хотя бы на базовом уровне), решила задать вопрос знающим в том людям. Как выглядит в моем представлении шаблон RAII для большинства API функций (с учетом 64-битных версий Windows)?

// обращаться к функциям освобождения ресурсов по адресу
typedef VOID (WINAPI *PFNCLEANUP)(UINT_PTR);
template<class T, PFNCLEANUP pfn, UINT_PTR inval = NULL>
class CResFree {
private:
  UINT_PTR m_res;
public:
  CResFree() { m_res = inval; } // конструктор по умолчанию
  // этот конструктор задает значение
  CResFree(T t) : m_res(reinterpret_cast<UINT_PTR>(t)) {}
  // здесь реализуется логика освобождения ресурсов
  ~CResFree() { Cleanup(); }
  // вспомогательная функция класса, позволяет установить
  // является ли ресурс валидным или нет
  BOOL IsValid() const { return (m_res != inval); }
  // если нужно переназначить данные нашего ресурса
  T operator=(T t) {
    Cleanup(); // освободили ресурс
    m_res = reinterpret_cast<UINT_PTR>(t); // задали новое значение
    return (*this); // вернули данные
  }
  // вернуть значение
  operator T() { return reinterpret_cast<T>(m_res); }
  // собственно функция очистки
  void Cleanup() {
    if (IsValid()) {
      pfn(m_res); // освободили ресурс
      m_res = inval; // потерли данные
    }
  }
};

Код я достаточно плотно закомментировала, так что если я в чем-то неправа, матерые кодеры C++ мне сразу укажут на ошибки. В чем состоит мой вопрос? Прежде всего насколько корректно мое представление о RAII? На мой взгляд все достаточно логично и каких-либо дополнительных перегрузок или еще чего-то не требуется. Но, повторюсь, это только на мой взгляд. Хотелось бы конструктивной критики. Также у меня есть вопрос как упростить объявление типа в последствии, так как на данный момент эти объявления относительно кода выше у меня выглядят так:

typedef CResFree<HANDLE, reinterpret_cast<PFNCLEANUP>(CloseHandle), reinterpret_cast<UINT_PTR>(INVALID_HANDLE_VALUE)> CCloseFile;

В C можно использовать макросы, но мне часто доводилось слышать что макросы в C++ использовать не стоит, лучше использовать встраиваемые (inline) функции. Однако встраиваемые функции жрут память как не в себя. Может тогда есть более лучший вариант RAII вообще, скажем, через лямбда?

READ ALSO
Как заставить работать QTimer

Как заставить работать QTimer

Есть следующая структура проекта: deviceh

134
Ассоциативные массивы С++

Ассоциативные массивы С++

Можно ли как-то отключить сортировку по ключи в контейнере типа map? Допустим, есть код:

151
Переадресовать двумерный массив

Переадресовать двумерный массив

Недавно нашел интереснейшую задачуОчень хочу ее решить, но нет никаких идей (кроме как условиями)

129
Как преобразовать a/b` в сумму чисел вида `1/n`?

Как преобразовать a/b` в сумму чисел вида `1/n`?

Задача: преобразовать a/b в сумму чисел вида 1/nНапример, когда a=3 и b=7, то программа должна вывести 3/7 = 1/3 + 1/11 + 1/231

112