Argomento correlatoOne-liner per RAII su non puntatore?
std::unique_ptr, deleters and the Win32 API
Per utilizzare un manico Win32 come Raii, posso utilizzare la seguente riga
std::unique_ptr<std::remove_pointer<HANDLE>::type, decltype(&CloseHandle)> m_mutex(CreateMutex(NULL, FALSE, NULL), &::CloseHandle);
Per me questo è un ambiente pulito one-liner e fa esattamente quello che Voglio.
Quando si tratta di SOCKET, non verrà compilato con questa stessa riga poiché SOCKET non può essere nullptr.
Cosa devo fare per farlo funzionare è la seguente:
struct SocketDeleter
{
typedef SOCKET pointer;
void operator()(SOCKET h)
{
::closesocket(h);
}
};
// Start listen socket.
std::unique_ptr<SOCKET, SocketDeleter> sock(socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_UDP));
Quello che non mi piace in questa implementazione è che ogni diverso tipo di ressources mi vorrà utilizzare, io è necessario copiare/incollare lo stesso codice per modificare solo la funzione di chiusura.
ho potuto utilizzare una macro, ma questo è davvero brutto e non può essere utilizzato due volte
#define RAII_UNIQUE_RESOURCE(varName, classType, init, closure) \
struct deleterMacro \
{ \
typedef classType pointer; \
void operator()(classType h) \
{ \
closure(h); \
} \
}; \
std::unique_ptr<classType, deleterMacro> varName(init);
// Compile, but breaks as soon as 2 sockets defined.
RAII_UNIQUE_RESOURCE(sock, SOCKET, socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_UDP), ::closesocket);
ho provato ad utilizzare un modello, ma non posso passare il mio puntatore a funzione alla funzione dell'operatore(), per quanto ne so.
template<class T, class methodDeclaration, class pFuncPointer>
struct deleter
{
typedef T pointer;
void operator()(T h)
{
// Is there a way??
methodDeclaration toCall = pFuncPointer;
toCall(h);
}
};
// With a call such as ...
std::unique_ptr<SOCKET, deleter<SOCKET, std::function<decltype(::closesocket)>, ::closesocket>> sock2(socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_UDP));
probabilmente si vorrà qualcosa di simile: 'template struct stateless_deleter {utilizzando il puntatore = T; void operator() (T x) {Deleter (x); }}; 'Usage:' std :: unique_ptr p (OpenSocket()); ' –
Perché preoccuparsi di' std :: unique_ptr'? Ci vorranno 5 minuti per scrivere un wrapper RAII o 30 secondi su Google. – Drop
@Drop perché scrivere una funzionalità personalizzata ** se ** ce n'è uno standard? – UmNyobe