mirror of
https://github.com/moses-smt/mosesdecoder.git
synced 2024-12-28 22:45:50 +03:00
110 lines
3.2 KiB
C++
110 lines
3.2 KiB
C++
#ifndef UTIL_SCOPED_H
|
|
#define UTIL_SCOPED_H
|
|
/* Other scoped objects in the style of scoped_ptr. */
|
|
|
|
#include "util/exception.hh"
|
|
#include <cstddef>
|
|
#include <cstdlib>
|
|
|
|
namespace util {
|
|
|
|
class MallocException : public ErrnoException {
|
|
public:
|
|
explicit MallocException(std::size_t requested) throw();
|
|
~MallocException() throw();
|
|
};
|
|
|
|
void *MallocOrThrow(std::size_t requested);
|
|
void *CallocOrThrow(std::size_t requested);
|
|
|
|
/* Unfortunately, defining the operator* for void * makes the compiler complain.
|
|
* So scoped is specialized to void. This includes the functionality common to
|
|
* both, namely everything except reference.
|
|
*/
|
|
template <class T, class Closer> class scoped_base {
|
|
public:
|
|
explicit scoped_base(T *p = NULL) : p_(p) {}
|
|
|
|
~scoped_base() { Closer::Close(p_); }
|
|
|
|
void reset(T *p = NULL) {
|
|
scoped_base other(p_);
|
|
p_ = p;
|
|
}
|
|
|
|
T *get() { return p_; }
|
|
const T *get() const { return p_; }
|
|
|
|
T *operator->() { return p_; }
|
|
const T *operator->() const { return p_; }
|
|
|
|
T *release() {
|
|
T *ret = p_;
|
|
p_ = NULL;
|
|
return ret;
|
|
}
|
|
|
|
protected:
|
|
T *p_;
|
|
|
|
private:
|
|
scoped_base(const scoped_base &);
|
|
scoped_base &operator=(const scoped_base &);
|
|
};
|
|
|
|
template <class T, class Closer> class scoped : public scoped_base<T, Closer> {
|
|
public:
|
|
explicit scoped(T *p = NULL) : scoped_base<T, Closer>(p) {}
|
|
|
|
T &operator*() { return *scoped_base<T, Closer>::p_; }
|
|
const T&operator*() const { return *scoped_base<T, Closer>::p_; }
|
|
};
|
|
|
|
template <class Closer> class scoped<void, Closer> : public scoped_base<void, Closer> {
|
|
public:
|
|
explicit scoped(void *p = NULL) : scoped_base<void, Closer>(p) {}
|
|
};
|
|
|
|
/* Closer for c functions like std::free and cmph cleanup functions */
|
|
template <class T, void (*clean)(T*)> struct scoped_c_forward {
|
|
static void Close(T *p) { clean(p); }
|
|
};
|
|
// Call a C function to delete stuff
|
|
template <class T, void (*clean)(T*)> class scoped_c : public scoped<T, scoped_c_forward<T, clean> > {
|
|
public:
|
|
explicit scoped_c(T *p = NULL) : scoped<T, scoped_c_forward<T, clean> >(p) {}
|
|
};
|
|
|
|
class scoped_malloc : public scoped_c<void, std::free> {
|
|
public:
|
|
explicit scoped_malloc(void *p = NULL) : scoped_c<void, std::free>(p) {}
|
|
|
|
void call_realloc(std::size_t to);
|
|
};
|
|
|
|
/* scoped_array using delete[] */
|
|
struct scoped_delete_array_forward {
|
|
template <class T> static void Close(T *p) { delete [] p; }
|
|
};
|
|
// Hat tip to boost.
|
|
template <class T> class scoped_array : public scoped<T, scoped_delete_array_forward> {
|
|
public:
|
|
explicit scoped_array(T *p = NULL) : scoped<T, scoped_delete_array_forward>(p) {}
|
|
|
|
T &operator[](std::size_t idx) { return scoped<T, scoped_delete_array_forward>::p_[idx]; }
|
|
const T &operator[](std::size_t idx) const { return scoped<T, scoped_delete_array_forward>::p_[idx]; }
|
|
};
|
|
|
|
/* scoped_ptr using delete. If only there were a template typedef. */
|
|
struct scoped_delete_forward {
|
|
template <class T> static void Close(T *p) { delete p; }
|
|
};
|
|
template <class T> class scoped_ptr : public scoped<T, scoped_delete_forward> {
|
|
public:
|
|
explicit scoped_ptr(T *p = NULL) : scoped<T, scoped_delete_forward>(p) {}
|
|
};
|
|
|
|
} // namespace util
|
|
|
|
#endif // UTIL_SCOPED_H
|