Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Annex: Alternatives

Boost , Chapter 1. Boost.ScopeExit 1.1.0 , Chapter 1. Boost.ScopeExit 1.1.0

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

В этом разделе представлены некоторые альтернативные и связанные работы с Boost.ScopeExit.

Try-Catch

Это пример использования плохо разработанного класса file. Пример file не закрывает файл в своем деструкторе, программист, как ожидается, назовет функцию Close. Например (см. также try_catch.cpp):

file passwd;
try {
    passwd.open("/etc/passwd");
    // ...
    passwd.close();
} catch(...) {
    std::clog << "could not get user info" << std::endl;
    if(passwd.is_open()) passwd.close();
    throw;
}

При этом следует отметить следующие вопросы:

  1. Объект passwd определяется за пределами блока try, поскольку этот объект требуется внутри блока catch для закрытия файла.
  2. Объект passwd не полностью построен до тех пор, пока не вернется функция open.
  3. При открытии бросков не следует называть passwd. Close(), отсюда и призыв к passwd.is_open().

Подход Boost.ScopeExit не имеет ни одного из этих вопросов. Например (см. также try_catch.cpp):

try {
    file passwd("/etc/passwd");
    BOOST_SCOPE_EXIT(&passwd) {
        passwd.close();
    } BOOST_SCOPE_EXIT_END
} catch(...) {
    std::clog << "could not get user info" << std::endl;
    throw;
}

RAII

RAII абсолютно идеально подходит для класса file, представленного выше. Использование правильно разработанного file класс будет выглядеть так:

try {
    file passwd("/etc/passwd");
    // ...
} catch(...) {
    std::clog << "could not get user info" << std::endl;
    throw;
}

Однако, используя RAII для создания сильной гарантии может ввести много неиспользуемых типов RAII. Например:

persons_.push_back(a_person);
pop_back_if_not_commit pop_back_if_not_commit_guard(commit, persons_);

Класс pop_back_if_not_commit либо определяется из сферы охвата, либо как местный класс:

class pop_back_if_not_commit {
    bool commit_;
    std::vector<person>& vec_;
    // ...
    ~pop_back_if_not_commit() {
        if(!commit_) vec_.pop_back();
    }
};

В некоторых случаях сильная гарантия может быть выполнена с помощью стандартных утилит:

std::auto_ptr<Person> superman_ptr(new superman());
persons_.push_back(superman_ptr.get());
superman_ptr.release(); // persons_ successfully took ownership

Boost.Multi-Index. .

Scope Guards

Представьте, что новый курс валюты введен до совершения транзакции (см. также []):

bool commit = false;
std::string currency("EUR");
double rate = 1.3326;
std::map<std::string, double> rates;
bool currency_rate_inserted =
        rates.insert(std::make_pair(currency, rate)).second;
// Transaction...

Если транзакция не завершена, валюта должна быть удалена из rates. Это можно сделать с помощью ScopeGuard и Boost.Lambda (или Boost.Phoenix):

using namespace boost::lambda;
ON_BLOCK_EXIT(
    if_(currency_rate_inserted && !_1) [
        bind(
            static_cast<
                std::map<std::string, double>::size_type
                (std::map<std::string, double>::*)(std::string const&)
            >(&std::map<std::string, double>::erase)
          , &rates
          , currency
        )
    ]
  , boost::cref(commit)
  );
// ...
commit = true;

При этом следует отметить следующие вопросы:

  1. Boost.Lambda выражений трудно писать правильно (например, перегруженные функции должны быть явно отброшены, как показано в примере выше).
  2. Условие в if_ выражение относится к commit переменной косвенно через _1 местоодержатель уменьшая читаемость.
  3. Установка точки разрыва внутри if_[...] требует глубокого знания Boost.Lambda и методов отладки.

Этот код будет выглядеть намного лучше с C++11 lambdas:

ON_BLOCK_EXIT(
    [currency_rate_inserted, &commit, &rates, &currency]() {
        if(currency_rate_inserted && !commit) rates.erase(currency);
    }
);
// ...
commit = true;

С Boost.ScopeExit мы можем просто сделать следующее (см. также scope_guard.cpp):

BOOST_SCOPE_EXIT(currency_rate_inserted, &commit, &rates, &currency) {
    if(currency_rate_inserted && !commit) rates.erase(currency);
} BOOST_SCOPE_EXIT_END
// ...
commit = true;

The D Programming Language

Boost.ScopeExit похож на функцию scope(exit), встроенную в язык программирования D.

Любопытный читатель может заметить, что библиотека не реализует scope(success) и scope(failure) языка D. К сожалению, это невозможно в C++, потому что условия неудачи или успеха не могут быть определены, позвонив по телефону std::uncaught_ exception (см. Guru of the Week #47 для деталей о std::uncaught_ exception и если он имеет какое-либо хорошее применение вообще). Однако это не большая проблема, потому что эти две конструкции D могут быть выражены в терминах scope(exit) и bool commit переменная (аналогично некоторым примерам, представленным в разделе Tutorial).

C++11 Lambdas

Используя C++11 lambdas, относительно легко реализовать Boost.ScopeExit конструкцию. Например (см. также world_cxx11_lambda.cpp):

#include <functional>
struct scope_exit {
    scope_exit(std::function<void (void)> f) : f_(f) {}
    ~scope_exit(void) { f_(); }
private:
    std::function<void (void)> f_;
};
void world::add_person(person const& a_person) {
    bool commit = false;
    persons_.push_back(a_person);
    scope_exit on_exit1([&commit, this](void) { // Use C++11 lambda.
        if(!commit) persons_.pop_back(); // `persons_` via captured `this`.
    });
    // ...
    commit = true;
}

Однако эта библиотека позволяет программировать Boost.ScopeExit конструкцию таким образом, чтобы она была переносной между компиляторами C++03 и C++11.


PrevUpHomeNext

Статья Annex: Alternatives раздела Chapter 1. Boost.ScopeExit 1.1.0 Chapter 1. Boost.ScopeExit 1.1.0 может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Chapter 1. Boost.ScopeExit 1.1.0 ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 18:27:02/0.025465965270996/1