2013-06-13 3 views
1

Я хочу создать охрану, которая блокирует функцию при построении и разблокирует ее при уничтожении, например. вызывая функцию с false и true.как создать защиту, похожую на boost :: lock_guard

class A { 
void enable(bool flag); 
}; 

внутри другого метода, я хочу использовать:

A::anotherMethod(...) { 
    block_guard(A::enable); // now A::enable(false) 
    // some operation 
} // now A::enable(true) 

мои идеи:

с помощью шаблона

template < class T > 
class block_guard { 
    T t_; 
public: 
    block_guard(T& t) : t_(t) { 
    t_(false); 
    } 
    ~block_guard() { 
    t_(true); 
    } 
}; 

вопрос, как создать экземпляр шаблон? возможно, с boost::bind?

используя подталкивание :: функция

class block_guard { 
    typedef boost::function< void (bool) > T; 
    T t_; 
public: 
    block_guard(T& t) : t_(t) { 
    t_(false); 
    } 
    ~block_guard() { 
    t_(true); 
    } 
}; 

это работает отлично, но вызов кажется очень сложным с

block_guard bg(boost::function< void (bool) >(boost::bind(&A::enable, pointer-to-A, _1)); 

любые идеи? Может быть, есть еще один, гораздо более простой способ?

ответ

2

Прежде всего, поймите, что функция-член не все, что вам нужно; вам также нужен объект для его вызова. В C++ нет способа для объекта, созданного в функции, для неявного захвата текущего указателя this.

Я собираюсь предположить, что у вас нет C++ 11. Если вы это сделаете, использование вашего второго решения с помощью выражения лямбда проще всего.

Теперь, если вам неинтересно небольшое повышение производительности boost :: function (и вам не следует), второе решение хорошо, но я бы немного изменил его, чтобы было удобнее использовать его вытягивая привязку в конструктор.

class block_guard { 
    typedef boost::function< void (bool) > block_fn; 
    block_fn block_fn_; 
public: 
    // For non-member functions and function objects: 
    template <typename Fn> 
    block_guard(Fn fn) : block_fn_(fn) { 
    block_fn_(false); 
    } 
    // For member functions: 
    template <typename T, typename Ret> 
    block_guard(T* obj, Ret (T::*fn)(bool)) : block_fn_(boost::bind(fn, obj, _1)) { 
    block_fn_(false); 
    } 
    ~block_guard() { 
    block_fn_(true); 
    } 
}; 

Использование:

block_guard guard(this, &A::enable); 

Я использую параметр Ret здесь, потому что нет никаких причин, чтобы не позволить функции, которые возвращают то - возвращаемое значение будет просто игнорируются.

Если вы не хотите boost :: function, вещь станет менее простой в использовании, потому что вам нужно создать шаблон защиты блока. Тогда становится полезным сделать block_guard специально для функций-членов. Вы также теряете способность использовать непустые функции.

template <typename T> 
class block_guard { 
    typedef void (T::*block_fn)(bool); 
    T* obj_; 
    block_fn block_fn_; 
public: 
    block_guard(T* obj, block_fn fn) : obj_(obj), block_fn_(fn) { 
    (obj_->*block_fn_)(false); 
    } 
    ~block_guard() { 
    (obj_->*block_fn_)(true); 
    } 
}; 

Использование:

block_guard<A> guard(this, &A::enable); 
+0

Можно ли добавить способ лямбда-выражения? я не очень хорошо знаком с этими ... –

+1

'block_guard guard ([this] (bool b) {enable (b);});' –

0

Да, есть гораздо более простой способ, забыть шаблоны, общие вещи и все, что не нужно и сосредоточиться на задаче.

Все, что вам нужно, это класс с ctor и dtor. Сначала напишите dtor, он покажет, что вам нужно будет работать. Затем напишите ctor, используя аргументы по мере необходимости. Наконец, удалите ненужные функции (cctor, op =). Готово.

Не общий, но прямо к делу.

Смежные вопросы