Информация об изменениях

Сообщение Re[3]: Как получить тип по указателю на него? от 26.06.2018 20:28

Изменено 27.06.2018 8:24 Кодт

Re[3]: Как получить тип по указателю на него?
Здравствуйте, LazyKarlson, Вы писали:

LK>Тоже работает, да, хотя введение дополнительной структуры.. ну.. шашечки. Но я не об этом. Не могу понять, почему вот так

LK>
LK>struct RegKeyDeleter
LK>{
LK>    //using pointer = HKEY;
LK>    void operator()(HKEY p) const
LK>    {
LK>        RegCloseKey(p);
LK>    }
LK>};

LK>using unique_reg_key = std::unique_ptr<HKEY, RegKeyDeleter>;
LK>

LK>не работает? Я всего лишь убрал переопределение типа...

Потому что так задумано. Чтобы можно было хранить в unique_ptr произвольные указатели.
https://en.cppreference.com/w/cpp/memory/unique_ptr
unique_ptr<T,Deleter> берёт тип "указатель" из Deleter::pointer, либо, если это не указано, считает указателем тип T*.

Правда, совсем уж произвольные типы там хранить не получится, (например, int с сигнальным значением -1 — всякие позиксовые дескрипторы).
А только NullablePointer.

Кстати говоря, HKEY тоже формально нельзя хранить: у него сигнальное значение INVALID_HANDLE_VALUE = (HKEY)(intptr_t)(-1).
Но практика показывает, что в WinAPI не встречаются хэндлы со значением 0. То есть, мы не получим здесь утечку ресурсов из-за того, что unique_ptr((HKEY)0) откажется вызывать RegCloseKey.

Кстати говоря!
Если уж писать на плюсах под WinAPI, то было бы очень естественно взять библиотеку ATL, в которой есть умные хэндлы. Конкретно, здесь — CRegKey.
Ну или если ATL тащить не хочется, то скопипастить своё — это же дело пары минут. Там не рокет саенс, всего-то — написать кучу стандартных методов.

class RegKey {
public:
  RegKey() {}
  explicit RegKey(HKEY h) : h_(h) {}
  RegKey(RegKey&& r) { r.swap(*this); }

  ~RegKey() { if (h_ != INVALID_HANDLE_VALUE) ::RegCloseKey(h_); }

  RegKey& operator = (HKEY h) { return *this = CRegKey(h); }
  RegKey& operator = (RegKey&& r) { r.swap(*this); return *this; }

  void swap(RegKey& r) { swap(h_, r.h_); }

  HKEY detach() { HKEY h = h_; h_ = INVALID_HANDLE_VALUE; return h; }
  HKEY get() const { return h_; }
  // operator * и -> смысла не имеют, т.к. HKEY не разыменуемый

  operator bool() const { return h_ != INVALID_HANDLE_VALUE; }

private:
  HKEY h_ = INVALID_HANDLE_VALUE;
};
Re[3]: Как получить тип по указателю на него?
Здравствуйте, LazyKarlson, Вы писали:

LK>Тоже работает, да, хотя введение дополнительной структуры.. ну.. шашечки. Но я не об этом. Не могу понять, почему вот так

LK>
LK>struct RegKeyDeleter
LK>{
LK>    //using pointer = HKEY;
LK>    void operator()(HKEY p) const
LK>    {
LK>        RegCloseKey(p);
LK>    }
LK>};

LK>using unique_reg_key = std::unique_ptr<HKEY, RegKeyDeleter>;
LK>

LK>не работает? Я всего лишь убрал переопределение типа...

Потому что так задумано. Чтобы можно было хранить в unique_ptr произвольные указатели.
https://en.cppreference.com/w/cpp/memory/unique_ptr
unique_ptr<T,Deleter> берёт тип "указатель" из Deleter::pointer, либо, если это не указано, считает указателем тип T*.

Правда, совсем уж произвольные типы там хранить не получится, (например, int с сигнальным значением -1 — всякие позиксовые дескрипторы).
А только NullablePointer.

Кстати говоря, HKEY тоже формально нельзя хранить: у него сигнальное значение INVALID_HANDLE_VALUE = (HKEY)(intptr_t)(-1).
Но практика показывает, что в WinAPI не встречаются хэндлы со значением 0. То есть, мы не получим здесь утечку ресурсов из-за того, что unique_ptr((HKEY)0) откажется вызывать RegCloseKey.

Кстати говоря!
Если уж писать на плюсах под WinAPI, то было бы очень естественно взять библиотеку ATL, в которой есть умные хэндлы. Конкретно, здесь — CRegKey.
Ну или если ATL тащить не хочется, то скопипастить своё — это же дело пары минут. Там не рокет саенс, всего-то — написать кучу стандартных методов.

class RegKey {
public:
  RegKey() {}
  explicit RegKey(HKEY h) : h_(h) {}
  RegKey(RegKey&& r) { r.swap(*this); }

  ~RegKey() { if (h_ != INVALID_HANDLE_VALUE) ::RegCloseKey(h_); }

  RegKey& operator = (HKEY h) { return *this = RegKey(h); }
  RegKey& operator = (RegKey&& r) { r.swap(*this); return *this; }

  void swap(RegKey& r) { swap(h_, r.h_); }

  HKEY detach() { HKEY h = h_; h_ = INVALID_HANDLE_VALUE; return h; }
  HKEY get() const { return h_; }
  // operator * и -> смысла не имеют, т.к. HKEY не разыменуемый

  operator bool() const { return h_ != INVALID_HANDLE_VALUE; }

private:
  HKEY h_ = INVALID_HANDLE_VALUE;
};