Что хочется: как-нибудь автоматически вывести тип, на который указывает указатель, имея только тип самого указателя.
Пример:
template < class T > class C
{
public:
C (T* t) {};
};
struct S
{
int _internal;
};
S* CreateS()
{
return new S();
}
typedef S* PS;
int main()
{
PS p = CreateS();
// Как получается
C < S > c1(p);
// Как хотелось бы, но не получается:
C < *PS > c2(p);
// Или что-то подобное.
}
Зачем: бывает так, что указатель описан в API,а то, на что он указывает, нет.
Откуда ноги поросли: Захотел HKEY из Win32 обернуть в unique_ptr с RegCloseKey в качестве deleter'a. Все хорошо, только в качестве типа в конструктор unique_ptr приходится передавать HKEY__, а не *HKEY или что-то подобное.
Здравствуйте, LazyKarlson, Вы писали:
LK>Откуда ноги поросли: Захотел HKEY из Win32 обернуть в unique_ptr с RegCloseKey в качестве deleter'a. Все хорошо, только в качестве типа в конструктор unique_ptr приходится передавать HKEY__, а не *HKEY или что-то подобное.
Конкретно для std::unique_ptr есть альтернатива — определенный тип pointer у класса Deleter'а
struct RegKeyDeleter
{
using pointer = HKEY;
void operator()(pointer p) const
{
RegCloseKey(p);
}
};
using unique_reg_key = std::unique_ptr<HKEY, RegKeyDeleter>;
Здравствуйте, LazyKarlson, Вы писали:
LK>Тоже работает, да, хотя введение дополнительной структуры.. ну.. шашечки. Но я не об этом. Не могу понять, почему вот так 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 тащить не хочется, то скопипастить своё — это же дело пары минут. Там не рокет саенс, всего-то — написать кучу стандартных методов.
Здравствуйте, watchmaker, Вы писали:
LK>>автоматически вывести тип, на который указывает указатель, имея только тип самого указателя.
W>std::remove_pointer_t
Да, но не стоит только забывать, что std::remove_pointer применим не только к указателям, а вообще к любым типам. Между тем, ТС собирается применять это к алиасам типов, для которых не известно, является ли данный тип указателем, или чем-то другим. Возможно, имело бы смысл определить собственную метафункцию, во избежание "сюрпризов". Ну хотя бы так:
К>Кстати говоря! К>Если уж писать на плюсах под WinAPI, то было бы очень естественно взять библиотеку ATL, в которой есть умные хэндлы. Конкретно, здесь — CRegKey. К>Ну или если ATL тащить не хочется, то скопипастить своё — это же дело пары минут. Там не рокет саенс, всего-то — написать кучу стандартных методов.
Оно да, но там надо пару ключей считать. Для этого ни ATL подключать, ни дополнительную структуру создавать не хотелось.
А вот вывод указателя из Deleter::pointer был для меня откровением. Спасибо!
Здравствуйте, rg45, Вы писали:
R>Да, но не стоит только забывать, что std::remove_pointer применим не только к указателям, а вообще к любым типам. Между тем, ТС собирается применять это к алиасам типов, для которых не известно, является ли данный тип указателем, или чем-то другим. Возможно, имело бы смысл определить собственную метафункцию, во избежание "сюрпризов". Ну хотя бы так:
Можно проще:
template <typename T>
using MySpecialRemovePointer = std::enable_if<std::is_pointer<T>::value, std::remove_pointer_t<T>>;
Здравствуйте, LazyKarlson, Вы писали:
LK>Оно да, но там надо пару ключей считать. Для этого ни ATL подключать, ни дополнительную структуру создавать не хотелось. LK>А вот вывод указателя из Deleter::pointer был для меня откровением. Спасибо!
Так и этак придётся новую структуру писать
— либо удалятор для типа, причём, не являющегося Nullable Pointer, и потому формально не подходящего для хранения в unique_ptr,
— либо умный хэндл с необходимым минимумом стандартных методов