Еще один scope_guard - с наворотами
От: TepMuHyc  
Дата: 23.09.03 10:28
Оценка: 9 (1)
Посмотрел я на МаксимовЕ
Автор: MaximE
Дата: 21.09.03
и Александресков scope_guard и подумал, что неплохо бы иметь в нем 2 метода:

— dismiss(), который отменяет вызов функтора (впрочем, это есть в вышеназванных реализациях)
— commit(), который вызывает функтор еще до того как дело дойдет до деструктора.

Придумалось вот такое решение:
class scope_guard_base {
    scope_guard_base& operator=(const scope_guard_base&);
protected:
    typedef void (*commit_fn)(const scope_guard_base*);
    mutable commit_fn m_commit; //функция коммита - устанавливается потомком

    scope_guard_base(commit_fn f)
        :m_commit(f)
        {}
    scope_guard_base(const scope_guard_base& rhs)
        :m_commit(rhs.m_commit)
        { rhs.m_commit = 0; }
public:
    ~scope_guard_base()
    {
        try{ 
            if( m_commit ) 
                m_commit( this ); 
        }catch(...){
            // некузяво бросаться исключениями из деструктора...
        } 
    }

    void dismiss() const
        { m_commit = 0; }

    void commit() const
    {    
        if( !m_commit ) return;
        commit_fn fn = m_commit;
        m_commit = 0;//коммитимся прямо сейчас - деструктору делать нечего.
        fn( this );
    }
};

template<class F> class scope_guard_impl
    :public scope_guard_base
{
    static void do_commit(const scope_guard_base* g);
    F m_f;
public:
    scope_guard_impl(const F& f)
        :scope_guard_base(do_commit)
        ,m_f(f)
        {}
};

template<class F> 
void scope_guard_impl<F>::do_commit(const scope_guard_base* g)
{
    ((scope_guard*)g)->m_f();
}

//все остальное как у MaximE и Александреску


Итак, плюсы:
— появился метод commit()

А теперь минусы:
— функция scope_guard_impl::do_commit() никак не может стать inline (компилятор не даст) потому что на нее имеется указатель. В принципе, это не так уж и страшно (особенно, если ее сделать __fastcall) — кода она негенерит считанные байты — но неприятный осадок все равно остается
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.