Вот статья, в которой говорится об идиоме под названием Rule of Zero.
Здесь выдержка:
class module {
public:
explicit module(std::wstring const& name)
: handle { ::LoadLibrary(name.c_str()), &::FreeLibrary } {}
// other module related functions go here
private:
using module_handle = std::unique_ptr<void, decltype(&::FreeLibrary)>;
module_handle handle;
};
Он повторно использует функции unique_ptr
RAII, поэтому вам не нужно заботиться о реализации сложной и многоплодной обертки из правила пяти.
Представленный таким образом (управляя ресурсами на основе ручек с помощью unique_ptr
, таким образом), это выглядит как взломать для меня, а не лучшее решение для того, что он пытается решить. Слишком много предположений подразумеваются неявно:
- Один из них способен сверять и использовать базовый тип, на который построен
#define
(илиtypedef
)HANDLE
. Для меня это должно быть скрытое знание, и решение должно основываться исключительно на том, что делает интерфейс:HANDLE
. - Ручки могут быть любыми, они не должны быть типами указателей.
Я бы хотел использовать эту идиому, но во многих ситуациях я наткнулся на нее.
Является ли эта обертка, сфокусированная на RAII, уже сделанной и полезной в какой-нибудь классной библиотеке? Все ли используют такой инструмент, и я не знаю? (Я считаю, что неплохо иметь такую оснастку не только для одного, но и для многих типов владельцев)
РЕДАКТИРОВАТЬ 1
Речь идет не о дескрипторах ресурсов платформы, например, glGenLists
возвращает вид дескриптора, a GLuint
, и вы должны называть glDeleteLists
на нем. Как уже указывалось, ручками ресурсов не являются типы указателей, и это предположение не следует принимать.
EDIT 2
Правило Zero, в прежнем примере, с использованием уже существующего инструмента, unique_ptr
, показывает как хороший ярлык для управления дескрипторами. Дополнительные предположения, которые он требует, заставляют его отстать. Правильные предположения состоят в том, что у вас есть дескриптор, и у вас есть функция уничтожения ресурсов, которая уничтожает ресурс, заданный дескриптором. Независимо от того, является ли дескриптор void *
, a GLuint
, что бы это ни было, это не имеет значения, и, что еще хуже, не нужно даже требовать сопоставить внутренний тип HANDLE
. Для управления ручками RAII, если идиома говорит об этом хорошо и не может применяться в таких ситуациях, я считаю, что это не хорошо для этого, наконец, с данным инструментом.
РЕДАКТИРОВАТЬ 3
Иллюстративная ситуация была бы, скажем, вы отвечаете за использование новой сторонней библиотеки C. Он содержит FooHandle create_foo()
и a void destroy_foo(FooHandle)
. Итак, вы думаете, "позвольте использовать FooHandle, используя правило нуля". Хорошо, вы идете с помощью unique_ptr
, a unique_ptr
к тому, что вы спрашиваете сами? Является FooHandle
указателем?, так что вы используете unique_ptr
to FooHandle
не подвергаемый базовый тип? Это int
?, так что вы можете использовать его прямо или лучше (re) typedef
вещи, подобные @NicolBolas, сделали в его ответе. Для меня это кажется явным, даже в такой тривиальной ситуации, unique_ptr
уже показывает, что он не идеально подходит для управления ручками ресурсов.
Отказ от ответственности:
Я попытался переформулировать и лучше выразить себя:
EDIT 4
Я нашел то, что искал, я поставил его как ответ в переформулированном вопросе: qaru.site/info/404574/....