Created
December 2, 2012 07:36
-
-
Save socantre/4187614 to your computer and use it in GitHub Desktop.
Code to make unique_ptr easy to use for generic cleanup code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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