raii::unique_rc is a small open-source C++ library which provides RAII wrapper for generic resource - anything that needs to be acquired, used, and eventually released.
If you like this project, please consider donating to one of the funds that help victims of the war in Ukraine: https://www.stopputin.net/.
The idea behind raii::unique_rc is similar to std::unique_ptr in providing automatic and exception-safe deallocation of dynamically allocated resource be it a memory, file descriptors, file handles, events, sockets, COM objects, GDI objects, etc.
The key difference is a requirement for 'deallocator', a functional object which deallocates resource, to provide what is viewed as invalid value. This approach is described in Kenny Kerr's artcle Windows with C++ - C++ and the Windows API. raii::unique_rc provides similar interface to std::unique_ptr, but unlike latter, which compares against pointer()
, raii::unique_rc requires deallocator to specify an invalid type and value e.g. INVALID_HANDLE_VALUE, INVALID_SOCKET, etc
.
To be added
- Interface similar to std::unique_ptr, with invalid type and invalid value defined in deallocator. This simplifies work with handles typically allocated via API function such as fopen, CreateFile, etc.
- Small code size consisting of just several files
unique_rc.hpp
,unique_ptr.hpp
,defs.hpp
and deallocators. - Clean warning-free codebase even on high warning levels such as
-Wall
-Wextra
-pedantic
. - Specialised raii::unique_ptr - equivalent to std::unique_ptr, derived from raii::unique_rc.
#include "unique_rc.hpp"
#include "stdio_fclose.hpp"
#include <stdio.h>
int main() {
raii::unique_rc<FILE *, raii::stdio_fclose> streamRC{ fopen("/tmp/test.txt", "r+") };
if (streamRC) {
// Do work here...
// Use streamRC.get() to get file descriptor
}
}
with stdio fclose deallocator
struct stdio_fclose
{
constexpr stdio_fclose() noexcept = default;
[[nodiscard]] static constexpr std::nullptr_t invalid() noexcept { return nullptr; }
void operator()(FILE *h) const noexcept { fclose(h); }
};
#include "unique_rc.hpp"
#include "windows_close_handle.hpp"
#include <windows.h>
int main() {
raii::unique_rc<HANDLE,
raii::close_handle_invalid_handle_value<HANDLE>> myFile{ CreateFile(/* params */) };
if (myFile) {
// Do your work...
// Use myFile.get() to get file HANDLE
}
}
with CloseHandle deallocator
template<typename Handle = HANDLE>
requires std::convertible_to<Handle, HANDLE>
struct close_handle_invalid_handle_value
{
constexpr close_handle_invalid_handle_value() noexcept = default;
[[nodiscard]] static constexpr Handle invalid() noexcept { return INVALID_HANDLE_VALUE; }
void operator()(Handle h) const noexcept { CloseHandle(h); }
};
#include "unique_ptr.hpp"
int main() {
raii::unique_ptr<int> intPtr = raii::make_unique<int>(23);
// Work with pointer, use *intPtr to get a value
}
- Kenny Kerr especially his article Windows with C++ - C++ and the Windows API
- Jason Turner and his awesome tutorial on cmake quick start C++ Weekly - Ep 208 - The Ultimate CMake / C++ Quick Start and C++ Weekly - Ep 376 - Ultimate CMake C++ Starter Template (2023 Updates)