1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
#ifndef INC_AUTO_HANDLE_H
#define INC_AUTO_HANDLE_H
// Like auto_ptr, but for arbitrary "handle" types.
// The parameters are:
// - handle_type: the type of the raw handle to be wrapped
// - closer_type: a function object type whose operator() takes a raw handle
// and closes it (or does nothing if it is a null handle)
// - factory_type: a function object type whose operator() returns a null
// handle
template<typename handle_type, typename closer_type, typename factory_type>
class auto_handle_ref;
template<typename handle_type, typename closer_type, typename factory_type>
class auto_handle
// Use inheritance so we can benefit from the empty base optimisation
: private closer_type, private factory_type
{
typedef auto_handle_ref<handle_type, closer_type, factory_type> ref_type;
public:
auto_handle()
: handle_(factory_type::operator()())
{}
explicit auto_handle(handle_type handle)
: handle_(handle)
{}
auto_handle(ref_type other)
: handle_(other.release())
{}
auto_handle & operator=(auto_handle & other)
{
reset(other.release());
}
~auto_handle()
{
reset();
}
handle_type get() const
{
return handle_;
}
handle_type release()
{
handle_type handle(handle_);
handle_ = factory_type::operator()();
return handle;
}
void reset()
{
closer_type::operator()(handle_);
handle_ = factory_type::operator()();
}
void reset(handle_type handle)
{
closer_type::operator()(handle_);
handle_ = handle;
}
operator ref_type()
{
return ref_type(*this);
}
private:
handle_type handle_;
};
template<typename handle_type, typename closer_type, typename factory_type>
class auto_handle_ref
{
typedef auto_handle<handle_type, closer_type, factory_type> target_type;
public:
explicit auto_handle_ref(target_type & target)
: target_(target)
{}
handle_type release()
{
return target_.release();
}
private:
target_type & target_;
};
#endif // !INC_AUTO_HANDLE_H
|