I've created a thing. The motivation of the thing is to provide ergonomics that std::unique_ptr falls short of:
void foo() {
auto file = raii_wrap(fopen("whatever.txt", "w"), [] (FILE* ptr) { fclose(ptr); });
fprintf(file, "hello world");
}
I'm also using c++11 so I don't have things like make_unique that might make it nicer. And without CTAD too it's a bit of a pain.
Implementation below:
template<
typename T,
typename D,
typename std::enable_if<
std::is_same<decltype(std::declval<D>()(std::declval<T>())), void>::value, int
>::type = 0
>
class raii_wrapper {
T obj;
optional<D> deleter;
public:
raii_wrapper(T&& obj, D deleter) : obj(std::move(obj)), deleter(deleter) {}
raii_wrapper(raii_wrapper&& other) : obj(std::move(other.obj)), deleter(other.deleter) {
other.deleter = nullopt;
}
raii_wrapper(const raii_wrapper&) = delete;
raii_wrapper& operator=(raii_wrapper&&) = delete;
raii_wrapper& operator=(const raii_wrapper&) = delete;
~raii_wrapper() {
if(deleter) {
deleter.unwrap()(obj);
}
}
operator T&() {
return obj;
}
operator const T&() const {
return obj;
}
};
template<
typename T,
typename D,
typename std::enable_if<
std::is_same<decltype(std::declval<D>()(std::declval<T>())), void>::value, int
>::type = 0
>
raii_wrapper<T, D> raii_wrap(T&& obj, D deleter) {
return {std::move(obj), deleter};
}