Skip to content

Instantly share code, notes, and snippets.

@socantre
Created December 2, 2012 07:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save socantre/4187614 to your computer and use it in GitHub Desktop.
Save socantre/4187614 to your computer and use it in GitHub Desktop.
Code to make unique_ptr easy to use for generic cleanup code
#include <utility> // std::forward
#include <memory> // std::unique_ptr
#include <type_traits> // std::remove_reference
#include <iostream> // std::cout
// The deleter types used with unique_ptr to do the cleanup
template<typename Handle, typename CleanupF>
struct Janitor : CleanupF {
using pointer = Handle;
Janitor(CleanupF &&cl) : CleanupF(std::move(cl)) {}
Janitor(CleanupF const &cl) : CleanupF(cl) {}
using CleanupF::operator();
};
template<typename CleanupF>
struct Janitor<void, CleanupF> : CleanupF {
using pointer = char;
Janitor(CleanupF &&cl) : CleanupF(std::move(cl)) {}
Janitor(CleanupF const &cl) : CleanupF(cl) {}
void operator() (pointer) { CleanupF::operator() (); }
};
// functions to create the unique_ptr to do cleanup
template<typename Handle, typename CleanupF>
std::unique_ptr<void, Janitor<typename std::remove_reference<Handle>::type, typename std::remove_reference<CleanupF>::type>>
make_janitor(Handle &&handle, CleanupF &&cleanupfunc) {
using Janitor_type = Janitor<typename std::remove_reference<Handle>::type, typename std::remove_reference<CleanupF>::type>;
return std::unique_ptr<void, Janitor_type>{
std::forward<Handle>(handle),
Janitor_type{std::forward<CleanupF>(cleanupfunc)}
};
}
template<typename CleanupF>
std::unique_ptr<void, Janitor<void, typename std::remove_reference<CleanupF>::type>>
make_janitor(CleanupF &&cleanupfunc) {
return std::unique_ptr<void, Janitor<void, typename std::remove_reference<CleanupF>::type>>{'a', {cleanupfunc}};
}
int main() {
// any cleanup code
auto janitor = make_janitor([]{std::cout << "Hello, World!\n";});
// cleanup of a specific handle
FILE *f = fopen("foo","rb");
auto janitor2 = make_janitor(f, [](FILE *f){ fclose(f); std::cout << "file closed\n"; });
std::cout << sizeof janitor << ' ' << alignof janitor << '\n';
std::cout << sizeof janitor2 << ' ' << alignof janitor2 << '\n';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment