Re[2]: do on exit
От: B0FEE664  
Дата: 18.03.15 16:51
Оценка:
Здравствуйте, Abyx, Вы писали:

A>я бы сказал что С++11 больше двух лет, а вы какой-то фигней занимаетесь.


Ну вот. Мы перешли на новый стандарт.
Автор: B0FEE664
Дата: 10.03.15
И как теперь правильно это написать?

std::shared_ptr<void> OnExit(nullptr, [&pList](void*){pList->pop_front();});

так?
И каждый день — без права на ошибку...
Re[5]: do on exit
От: nen777w  
Дата: 18.03.15 16:56
Оценка:
BFE>>>Неужели в boost нет ничего более подходящего?
EP>>Boost.ScopeExit
BFE>Нет, макросы мне не нужны.

Я поражаюсь С++ — офигенный язык, с такими классными возможностями, тут каждый найдёт себе что хочет.
Одни например goto боятся другие макросов...
Отредактировано 18.03.2015 16:56 nen777w . Предыдущая версия .
Re[6]: do on exit
От: B0FEE664  
Дата: 18.03.15 17:25
Оценка:
Здравствуйте, nen777w, Вы писали:

N>Я поражаюсь С++ — офигенный язык, с такими классными возможностями, тут каждый найдёт себе что хочет.

N>Одни например goto боятся другие макросов...

Я их не боюсь. Я их ненавижу.
И каждый день — без права на ошибку...
Re[3]: do on exit
От: Abyx Россия  
Дата: 18.03.15 20:31
Оценка:
Здравствуйте, B0FEE664, Вы писали:

A>>я бы сказал что С++11 больше двух лет, а вы какой-то фигней занимаетесь.


BFE>Ну вот. Мы перешли на новый стандарт.
Автор: B0FEE664
Дата: 10.03.15
И как теперь правильно это написать?


BFE>
BFE>std::shared_ptr<void> OnExit(nullptr, [&pList](void*){pList->pop_front();});
BFE>

BFE>так?

я уже писал ниже,
auto a = std::move(pList->front());
pList->pop_front();
a.f();


но если у тебя тип не перемещаемый, то тебе нужен unique_ptr, он легче чем shared_ptr и семантически правильней
std::unique_ptr<std::list<A>, void(*)(std::list<A>* p)> remover(pList.get(), [](std::list<A>* p){ p->pop_front(); });


или можно взять/написать какой-нибудь at_scope_exit
In Zen We Trust
Re[4]: do on exit
От: B0FEE664  
Дата: 19.03.15 10:55
Оценка:
Здравствуйте, Abyx, Вы писали:

A>я уже писал ниже,

A>
A>auto a = std::move(pList->front());
A>pList->pop_front();
A>a.f();
A>

Это вариант. Но меня больше интересует at_scope_exit.

A>но если у тебя тип не перемещаемый, то тебе нужен unique_ptr, он легче чем shared_ptr и семантически правильней

A>
A>std::unique_ptr<std::list<A>, void(*)(std::list<A>* p)> remover(pList.get(), [](std::list<A>* p){ p->pop_front(); });
A>

Это какой-то ужас: три раза по "std::list<A>"! Нет уж, слишком длинно.

A>или можно взять/написать какой-нибудь at_scope_exit


Ну я вот подумал и вижу два варианта, но в коде не уверен, так как не писал ещё такого:

Можно так:
class at_scope_exit4
{
  public:
    template <class F>
    at_scope_exit4(F&& f): m_f(std::forward<F>(f)){}
   ~at_scope_exit4()
    {
        try{ m_f(); }catch(...){assert(false);}
    }
  private:
    std::function<void()> m_f;
};


использование:
auto oOnExit4 = at_scope_exit4([&pList](){pList->pop_front();});



Наверное можно ещё и так:
template <class F>
class at_scope_exit5
{
  public:
    at_scope_exit5(F&& f): m_f(std::forward<F>(f)){}
   ~at_scope_exit5()
    {
        try{ m_f(); }catch(...){assert(false);}
    }
  private:
    F m_f;
};

template <class F>
inline
at_scope_exit5<F> make_at_scope_exit5(F&& f)
{
   return std::forward<F>(f);
}


использование:
      auto oOnExit5 = make_at_scope_exit5([&pList](){pList->pop_front();});


Ну, а какой вариант правильный?
И каждый день — без права на ошибку...
Re[4]: do on exit
От: B0FEE664  
Дата: 19.03.15 11:00
Оценка:
Здравствуйте, Erop, Вы писали:

E>Попробуй объяснить, что конкретно тебе надо-то?


На данный момент разыскивается хорошая RAII обёртка в рамках стандарта С++11 для произвольного замыкания. вроде этих
Автор: B0FEE664
Дата: 19.03.15
.
И каждый день — без права на ошибку...
Re[7]: do on exit
От: nen777w  
Дата: 19.03.15 11:43
Оценка:
N>>Я поражаюсь С++ — офигенный язык, с такими классными возможностями, тут каждый найдёт себе что хочет.
N>>Одни например goto боятся другие макросов...

BFE>Я их не боюсь. Я их ненавижу.

"Страх рождает гнев, гнев рождает ненависть."(С) не помню кто
Re[8]: do on exit
От: B0FEE664  
Дата: 19.03.15 12:22
Оценка:
Здравствуйте, nen777w, Вы писали:

N>>>Я поражаюсь С++ — офигенный язык, с такими классными возможностями, тут каждый найдёт себе что хочет.

N>>>Одни например goto боятся другие макросов...
BFE>>Я их не боюсь. Я их ненавижу.
N>"Страх рождает гнев, гнев рождает ненависть."(С) не помню кто

Зачем макросы если вот здесь
Автор: B0FEE664
Дата: 19.03.15
и так всё работает?
И каждый день — без права на ошибку...
Re[5]: do on exit
От: Evgeny.Panasyuk Россия  
Дата: 19.03.15 12:52
Оценка: 2 (1) +1
Здравствуйте, B0FEE664, Вы писали:

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

BFE>
BFE>      auto oOnExit5 = make_at_scope_exit5([&pList](){pList->pop_front();});
BFE>


Можно ещё вот так:
{
    auto &&guard = aux * []
    {
        cout << "end of scope" << endl;
    };
    cout << "begin of scope" << endl;
}

  Скрытый текст
#include <iostream>
#include <utility>

template<typename F>
class Guard
{
    F f;
public:
    Guard(const Guard&) = delete;
    Guard(Guard&&) = delete;
    Guard &operator=(const Guard&) = delete;
    Guard &operator=(Guard&&) = delete;

    template<typename T>
    Guard(T &&f)
        : f(std::forward<T>(f))
    {}
    ~Guard() noexcept(noexcept(f()))
    {
        f();
    }
};
 
struct Aux
{
    template<typename F>
    Guard<std::decay_t<F>> operator*(F &&f) const
    {
        return { std::forward<F>(f) };
    }
} constexpr aux{};

using namespace std;

int main()
{
    auto &&guard = aux * []
    {
        cout << "end of scope" << endl;
    };
    cout << "begin of scope" << endl;
}
Re[9]: do on exit
От: Evgeny.Panasyuk Россия  
Дата: 19.03.15 12:56
Оценка:
Здравствуйте, B0FEE664, Вы писали:

N>>>>Я поражаюсь С++ — офигенный язык, с такими классными возможностями, тут каждый найдёт себе что хочет.

N>>>>Одни например goto боятся другие макросов...
BFE>>>Я их не боюсь. Я их ненавижу.
N>>"Страх рождает гнев, гнев рождает ненависть."(С) не помню кто
BFE>Зачем макросы если вот здесь
Автор: B0FEE664
Дата: 19.03.15
и так всё работает?


Изначально речь шла про pre-C++11

http://rsdn.ru/forum/cpp/5116851.1


BFE>А как надо? (В рамках старого стандарта).

Re[6]: do on exit
От: Abyx Россия  
Дата: 19.03.15 13:28
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Можно ещё вот так:


можно же просто хранить ссылку, а она продлит время жизни лямбды
http://coliru.stacked-crooked.com/a/cf93a63c93859758
In Zen We Trust
Re[7]: do on exit
От: B0FEE664  
Дата: 19.03.15 13:55
Оценка:
Здравствуйте, Abyx, Вы писали:

A>можно же просто хранить ссылку, а она продлит время жизни лямбды

A>http://coliru.stacked-crooked.com/a/cf93a63c93859758
ой ли?
Почему вывод не 42, а непонятное 1?

g++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
begin of scope
1: guard 2
guard 1

И каждый день — без права на ошибку...
Re[8]: do on exit
От: Abyx Россия  
Дата: 19.03.15 13:57
Оценка:
Здравствуйте, B0FEE664, Вы писали:

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


A>>можно же просто хранить ссылку, а она продлит время жизни лямбды

A>>http://coliru.stacked-crooked.com/a/cf93a63c93859758
BFE>ой ли?
BFE>Почему вывод не 42, а непонятное 1?

BFE>

BFE>g++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
BFE>begin of scope
BFE>1: guard 2
BFE>guard 1


ну значит нельзя.
In Zen We Trust
Re[7]: do on exit
От: Evgeny.Panasyuk Россия  
Дата: 19.03.15 13:58
Оценка:
Здравствуйте, Abyx, Вы писали:

A>можно же просто хранить ссылку, а она продлит время жизни лямбды

A>http://coliru.stacked-crooked.com/a/cf93a63c93859758

Не, продлевается только время жизни результата выражения — http://coliru.stacked-crooked.com/a/1f4d6e661b5b1eab
В этом кстати засада с expression templates, то есть биндить их к auto&& нужно с осторожностью, а то данные на которые они ссылаются могут разрушиться к моменту вычисления.
Re[6]: do on exit
От: B0FEE664  
Дата: 19.03.15 14:36
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

Зачем здесь амперсанды?
EP> auto &&guard = aux * []
EP> {
EP> cout << "end of scope" << endl;
EP> };
И каждый день — без права на ошибку...
Re[7]: do on exit
От: B0FEE664  
Дата: 19.03.15 15:07
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Зачем здесь амперсанды?

EP>> auto &&guard = aux * []
EP>> {
EP>> cout << "end of scope" << endl;
EP>> };

PS Наверно, чтобы избежать копирования...
И каждый день — без права на ошибку...
Re[8]: do on exit
От: Evgeny.Panasyuk Россия  
Дата: 19.03.15 16:36
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>>Зачем здесь амперсанды?

EP>>> auto &&guard = aux * []
EP>>> {
EP>>> cout << "end of scope" << endl;
EP>>> };
BFE>PS Наверно, чтобы избежать копирования...

Да, это продлевает время жизни оригинального временного объекта до конца scope (также как и const &x = foo(); в предыдущих стандартах).
Помимо этого там используется copy-list-initialization — return { x };, в результате чего Guard может быть полностью non-copyable и non-movable (то есть не будет ни копий, ни перемещений, ни всяких copy/move elision).
Re[9]: do on exit
От: B0FEE664  
Дата: 19.03.15 17:45
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Да, это продлевает время жизни оригинального временного объекта до конца scope (также как и const &x = foo(); в предыдущих стандартах).

EP>Помимо этого там используется copy-list-initialization — return { x };, в результате чего Guard может быть полностью non-copyable и non-movable (то есть не будет ни копий, ни перемещений, ни всяких copy/move elision).

С Guard более-менее понятно, а вот одно копирование лямбды будет так или иначе(в момент создания Guard). Видимо надо завести ещё один Guard для указателя на функтор...
Кстати, зачем std::decay_t<F> ? Почему не typename std::decay<F>::type ? В этом есть какой-то сакральный смысл?


PS Тем, кто досюда дочитал, шутка дня:

What is std::decay and when it should be used?
It's obviously used to decay radioactive std::atomic types into non-radioactive ones.

отсюда
И каждый день — без права на ошибку...
Re[10]: do on exit
От: andyp  
Дата: 19.03.15 17:58
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:


BFE>Кстати, зачем std::decay_t<F> ? Почему не typename std::decay<F>::type ? В этом есть какой-то сакральный смысл?


template< class T >
using decay_t = typename decay<T>::type;


Alias template. Меньше букв.
Re[10]: do on exit
От: Evgeny.Panasyuk Россия  
Дата: 19.03.15 20:42
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>С Guard более-менее понятно, а вот одно копирование лямбды будет так или иначе(в момент создания Guard).


Там будет одно перемещение.

BFE>Видимо надо завести ещё один Guard для указателя на функтор...


Вот так?
{
    auto lambda = []
    {
        cout << "end of scope" << endl;
    };
    auto &&guard = make_guard(lambda); // takes reference to lambda

    cout << "begin of scope" << endl;
}
Думаю одно перемещение не настолько страшно, тем более после инлайнинга оно скорей всего испарится.
Да и теряется возможно обернуть всё это в удобный макрос:
{
    scope_exit
    {
        cout << "end of scope" << endl;
    };
    cout << "begin of scope" << endl;
}


BFE>Кстати, зачем std::decay_t<F> ? Почему не typename std::decay<F>::type ?


Как уже выше сказали — меньше букв.

BFE>В этом есть какой-то сакральный смысл?


Это был такой тонкий намёк на то что на дворе уже C++14
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.