Scope Guard средствами C++0x: часть 2

Более глубокое погружение в C++0x

В прошлой части была рассмотрена реализация Scope Guard средствами . Благодаря шаблонам с переменным количеством параметров (variadic templates), реализация на получилась несколько проще, чем в оригинале, так как один и тот же шаблонный класс может использоваться для создания с различным количеством параметров.

Но, как было отмечено, предыдущая реализация не являлась оптимальной в плане количества строк. Можно сделать проще и короче.

Одна из проблем предыдущей реализации — необходимость наличия отдельного класса, если Scope Guard потребуется вызывать метод какого-либо класса.

Иными словами, требуется две реализации: одна для Scope Guard, работающего с обычными функциями, другая — для Scope Guard, работающего с методами. Как оказалось, данная проблема решаема.

Основную (на мой взгляд) неочевидность в коде создавал метод развёртки std::tuple (Apply_Helper).

Хорошая новость заключается в том, что благодаря std::bind() обе проблемы очень легко решаются.

Реализация XGuard теперь сильно упрощается:

[-]
View Code C++
template<typename Function>
class XGuard {
public:
    XGuard(Function aFunction)
        : m_fSucceeded{false}, m_Function(aFunction)
    {
    }

    ~XGuard(void)
    {
        if (!this->m_fSucceeded) {
            try {
                this->m_Function();
            }
            catch(...) {
            }
        }
    }

    XGuard(const XGuard&& other) : m_fSucceeded(other.m_fSucceeded), m_Function(other.m_Function)
    {
        other.commit();
    }

    void commit(void) const throw()
    {
        this->m_fSucceeded = true;
    }

private:
    mutable bool m_fSucceeded;
    Function m_Function;

    XGuard(const XGuard&) = delete;
    XGuard& operator=(const XGuard&) = delete;
};

А благодаря type inference очень легко написать функцию, которая будет создавать XGuard:

[-]
View Code C++
template<typename F, typename... A>
auto makeXGuard(F f, const A&&... p) -> XGuard<decltype(std::bind(f, p...))>
{
    auto func = std::bind(f, p...);
    return XGuard<decltype(func)>(func);
}

Фокус в том, что передавая в функцию parameter pack (который const A&&... p), мы не можем априорно знать, какой результат вернёт std::bind() для таких аргументов. Использование вывода типов и альтернативный синтаксис функций приходят на помощь, в результате чего мы получили такой код.

Для возможности работы с методами классов нужно создать еще один вариант makeXGuard():

[-]
View Code C++
template<typename C, typename M, typename... A>
auto makeXGuard(C& c, M m, const A&&... p) -> XGuard<decltype(std::bind(m, c, p...))>
{
    auto func = std::bind(m, c, p...);
    return XGuard<decltype(func)>(func);
}

Вот так всё просто.

Автор: ; опубликовано в: C/C++; метки: C++0x, C/C++, Scope Guard
26
Апр
2010

RSS Комментарии к статье «Scope Guard средствами C++0x: часть 2» (4)  »

  1. [...] This post was mentioned on Twitter by Интернет заработок. Интернет заработок said: V.Kolesnikov: Scope Guard средствами C++0x: часть 2 [...]

  2. Максим

    Как же это не похоже на тот C++, что я знаю :) Поскорей бы Бьерн выпустил новую книжку … Возможно тогда мне такой код станет очевидным :)

    • Так стандарт еще окончательно не принят :-) Так что придётся ждать.

      Но если английский язык не является помехой, то рекомендую Wikipedia и этот замечательный FAQ.

  3. А мне нравится программирование)) Правда больше по C++ Builder специализируюсь)). Даже пару миниигр делал…. Да и не очень он и сложен я бы даже сказал.

Пожалуйста, не используйте эту форму для комментирования! Данная форма предназначена исключительно для ботов.

Оставить комментарий к записи «Scope Guard средствами C++0x: часть 2»

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, вы выражаете своё согласие с Правилами комментирования.

Подписаться, не комментируя

गते गते पारगते पारसंगते बोधि स्वाहा