Skip to content

Instantly share code, notes, and snippets.

@cjxgm
Created September 8, 2014 10:55
Show Gist options
  • Save cjxgm/ea0b8b912f5321b1ba52 to your computer and use it in GitHub Desktop.
Save cjxgm/ea0b8b912f5321b1ba52 to your computer and use it in GitHub Desktop.
c++ raii unique resource
#include <cstddef>
#include <type_traits>
#include <utility>
#include <functional>
#include <stdexcept>
#include <iostream>
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
namespace tue
{
template <class T, T null=T{}>
struct unique_res
{
using self_type = unique_res;
using self_ref = self_type &;
using self_rref = self_type &&;
using self_cref = self_type const&;
using value_type = std::remove_reference_t<T>;
using deleter_type = std::function<void(value_type)>;
using deleter_cref = deleter_type const&;
using deleter_ref = deleter_type &;
static constexpr auto null_value = null;
static_assert(std::is_pod<value_type>(), "T must be a plain-old-data.");
// constructor
unique_res() : unique_res(null_value, {}) {}
unique_res(value_type value, deleter_type deleter)
: value(value), deleter(deleter) {}
// observer
value_type get () const { return value ; }
deleter_ref & get_deleter() { return deleter; }
deleter_cref& get_deleter() const { return deleter; }
operator value_type() const { return get(); }
operator bool () const { return (get() != null_value); }
// destructor
~unique_res()
{
if (get() == null_value) return;
if (!get_deleter())
throw std::logic_error{"no deleter: may cause memory leak"};
get_deleter()(value);
}
// modifier
value_type release()
{
auto x = value;
value = null_value;
return x;
}
void swap(self_ref other)
{
std::swap(value, other.value);
std::swap(deleter, other.deleter);
}
void swap(self_rref other) { swap(other); }
void reset(value_type v=null_value) { swap({v, deleter}); }
// copy-move
unique_res(self_cref) = delete;
self_ref operator=(self_cref) = delete;
unique_res(self_rref other) : unique_res() { swap(other); }
self_ref operator=(self_rref other)
{
self_type empty;
swap(empty);
swap(other);
return *this;
}
private:
value_type value;
deleter_type deleter;
};
}
int main()
{
auto deleter_one = [](int x) { cout << "1: " << x << endl; };
auto deleter_two = [](int x) { cout << "1: " << x << endl; };
using unique_one = tue::unique_res<int, 1>;
unique_one one(1, deleter_one);
unique_one two(1, deleter_two);
one.reset(3);
one.reset(2);
two = std::move(one);
one.reset(1);
one.reset(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment