#ifndef CLEANER_H
#define CLEANER_H

template<typename T, void (*F)(T&)>
class Cleaner final {
    T wrapped;

public:
    Cleaner() {
    }

    Cleaner(const T& t) : wrapped(t) {
    }

    ~Cleaner() {
        F(wrapped);
    }

    Cleaner(const Cleaner&) = delete;
    Cleaner(Cleaner&&) = delete;
    Cleaner& operator=(const Cleaner&) = delete;
    Cleaner& operator=(Cleaner&&) = delete;

    T* operator->() {
        return &wrapped;
    }

    T* operator&() {
        return &wrapped;
    }

    operator const T() const {
        return wrapped;
    }

    operator T() {
        return wrapped;
    }
};

#endif