Re[3]: finally
От: PM  
Дата: 07.12.15 08:58
Оценка:
Здравствуйте, Karamat, Вы писали:

K>там все гораздо хуже


K>

K>в функции используется АПИ, требующее ссылок типа std::vector<MyClass1*>


Можно:
а) поменять API на
some_extern_api(std::vector<MyClass1> const&)

б) сделать
std::transform(vector_of_values, vector_of_pointers, std::addressof)


PM>>Используйте value типы, там где это возможно, обычно это упрощает код


K>Там по настоящему более общая задача — в функции надо гарантированно выполнить определенные действия, даже если возникнет исключение. Поэтому не важно, указатель или value. Для такого придумали finally, а в С++, на мой взгляд, минимальный оверхед будет при таком коде:


K>
K>void FunA(int a, int b, int c)
K>{
K>    try
K>    {
K>        //код функции
K>    }
K>    catch(...)
K>    {
K>        FunAFinally(a, b, c);
K>        throw;
K>    }
K>    FunAFinally(a, b, c);
K>}

K>void FunAFinally(int a, int b, int c)
K>{
K>    //код финализатора
K>}
K>


В языке для этого есть RAII, finally это где-то там, за углом, в Java мире.

Чтобы уменьшить синтаксический оверхед от одноразовых RAII, лет 10 назад добавили Boost.ScopeExit. В C++11 это делается лямбдой, т.е. чисто языковыми средствами.

В последнее время это развивается в scope(exit), scope(failure):
* http://habrahabr.ru/post/270545/
* Другой взгляд на исключения
Re[7]: finally
От: _hum_ Беларусь  
Дата: 08.12.15 10:07
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, _hum_, Вы писали:


__>>ну, а если кто-то сделает два клинера одного объекта, или не отпустит, или отпустит раньше времени и т.п.


К>или забудет написать finally, или возьмёт невладеющий контейнер вместо владеющего, и т.п.


вот-вот. потому и ищут разработчики языков и сами программисты подходы, позволяющие свести к минимуму подобные ошибки, а не разводят руками и говорят "ну, а что же вы хотели. с++ не для слабаков".

__>>все-таки ооп в первую очередь и задумывалось для того, чтобы не разбрасывать по коду объект и действия над ним, дабы максимально уменьшить вероятность подобных ошибок.


К>Это не вполне вопрос ООП.

К>Напротив, здесь больше пахнет ФП, т.к. по месту выполняется слияние трёх задач
К>- хранение коллекции
К>- управление временем жизни элементов
К>- реакция на коммит/ролбек

ну, поначалу задача выглядела как чисто опп-шная — есть набор объектов старого кода, и нужно:
— наделить объекты возможностью RAII
— оставить совместимость с предыдущим кодом.

но когда дальше речь пошла уже о каких-то сложных схемах пост-обработки исключений, то, конечно, все это перестало быть подходящим решением.



К>Если сценарий "хранить и убивать элементы при смерти контейнера" не одноразовый, — то нужны соответсвующие контейнеры. Тот же boost::ptr_vector.

К>И желательно протащить их в интерфейс, чтоб принимающая сторона тоже работала с ними.
К>А если именно по месту, то — либо писать финализатор (заделывать прореху синтаксиса С++), либо RAII-обёртку.

К>А в рамках ООП — наследоваться от стандартных контейнеров — моветон.

К>Потому что они не заточены на полиморфизм времени исполнения. И писать "virtual ~my_derived_vector()" — это обманывать сам себя.

а можно подробнее? что значит "заточенность на динамический полиморфизм" и "обманывать себя"?
Re: finally
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 08.12.15 10:24
Оценка:
Здравствуйте, Karamat, Вы писали:

K>при генерации исключения надо прибить все объекты, которые накопились в коллекциях

K>есть ли возможность это сделать без десятков строк идиотского кода ?

А так?

class MyFun
{
    public:
        MyFun();
        ~MyFun(); // гарантировано вызовется
        void operator () () // а то и просто метод MyFun::run()
        {
            // дальше идет тяжелая работа с коллекциями, где создаются и добавляются в эти коллекции экземпляры
            // MyClass1..MyClassN, при этом в любой момент может выскочить исключение
        }

    private:
        std::vector<MyClass1*> v1;
        std::list<MyClass2*> v2;
        ...
        std::map<MyClassN*, MyClassN1*> vN;
};

{ MyFun myFun; myFun(); }


Не так уж и много дополнительного кода... Плюс в качестве бонуса появляется возможность легко разбивать логику на отдельные методы.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.