do on exit
От: B0FEE664  
Дата: 28.03.13 14:29
Оценка:
Макросы не предлагать.

Что лучше variant 1 или 2?
И вообще, что бы вы сказали увидев это в проекте?

class A
{
  int m_n;
public:
  A(int n) : m_n(n) {}

  void f()
  { 
    if ( 0 == m_n )
      throw std::runtime_error("zero here");
    
    std::cout << m_n << std::endl;
  }
};


int main()
{
  boost::shared_ptr< std::list<A> > pList(new std::list<A>);

  pList->push_back(A(1));
  pList->push_back(A(2));
  pList->push_back(A(3));
  pList->push_back(A(4));
  pList->push_back(A(0));
  pList->push_back(A(5));

  void* pNull = NULL;

  while(pList->size())
  {
    try
    {
      A& rA = pList->front();
      //boost::shared_ptr< std::list<A> > OnExit(pList.get(), boost::mem_fn(&std::list<A>::pop_front)); // variant 1
      boost::shared_ptr<void> OnExit(pNull, boost::bind(&std::list<A>::pop_front, pList));              // variant 2
      
      rA.f();
    }
    catch(std::exception& e)
    {
      std::cout << "Error: " << e.what() << std::endl;
    }
  }

  std::cout << "Press any key to exit..." << std::endl;
  char ch = getch();
  
  return 0;
}

);

pList-
И каждый день — без права на ошибку...
exit shared_ptr bind
Re: do on exit
От: uzhas Ниоткуда  
Дата: 28.03.13 14:33
Оценка: :))) :))
Здравствуйте, B0FEE664, Вы писали:

BFE>И вообще, что бы вы сказали увидев это в проекте?


это недопустимо
класс A надо переименовать в CA
Re[2]: do on exit
От: B0FEE664  
Дата: 28.03.13 14:42
Оценка:
Здравствуйте, uzhas, Вы писали:

BFE>>И вообще, что бы вы сказали увидев это в проекте?

U>это недопустимо
U>класс A надо переименовать в CA

Вот вы смеётесь, а я сижу и думаю: commit'ить или не поймут...
И каждый день — без права на ошибку...
Re: do on exit
От: Abyx Россия  
Дата: 28.03.13 16:42
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

BFE>Макросы не предлагать.


BFE>Что лучше variant 1 или 2?

BFE>И вообще, что бы вы сказали увидев это в проекте?

я бы сказал что С++11 больше двух лет, а вы какой-то фигней занимаетесь.
In Zen We Trust
Re: do on exit
От: Erop Россия  
Дата: 28.03.13 19:00
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Что лучше variant 1 или 2?

BFE>И вообще, что бы вы сказали увидев это в проекте?

Зачем так сложно-то?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: do on exit
От: B0FEE664  
Дата: 28.03.13 20:29
Оценка:
Здравствуйте, Erop, Вы писали:

BFE>>Что лучше variant 1 или 2?

BFE>>И вообще, что бы вы сказали увидев это в проекте?
E>Зачем так сложно-то?

А как надо? (В рамках старого стандарта).
И каждый день — без права на ошибку...
Re: do on exit
От: Caracrist https://1pwd.org/
Дата: 28.03.13 20:42
Оценка:
Здравствуйте, B0FEE664, Вы писали:


BFE>  while(!pList->empty())
BFE>  {
BFE>    try
BFE>    {
BFE>      pList->front().f();
BFE>    }
BFE>    catch(std::exception& e)
BFE>    {
BFE>      std::cout << "Error: " << e.what() << std::endl;
BFE>    }
        pList->pop_front();
BFE>  }

если у тебя pop_front упадёт, то catch тебе скорее всего уже не поможет, а, иначе, зачем все эти сложности?
~~~~~
~lol~~
~~~ Single Password Solution
Re[2]: do on exit
От: B0FEE664  
Дата: 28.03.13 23:18
Оценка:
Здравствуйте, Caracrist, Вы писали:

C>если у тебя pop_front упадёт, то catch тебе скорее всего уже не поможет,

C>а, иначе, зачем все эти сложности?

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

boost::shared_ptr<void> OnExit(pNull, boost::bind(&std::list<A>::pop_front, pList));


Неужели в boost нет ничего более подходящего?
И каждый день — без права на ошибку...
Re[3]: do on exit
От: Evgeny.Panasyuk Россия  
Дата: 28.03.13 23:25
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Неужели в boost нет ничего более подходящего?


Boost.ScopeExit
Re: do on exit
От: Abyx Россия  
Дата: 28.03.13 23:34
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

BFE>
BFE>      A& rA = pList->front();
BFE>      //boost::shared_ptr< std::list<A> > OnExit(pList.get(), boost::mem_fn(&std::list<A>::pop_front)); // variant 1
BFE>      boost::shared_ptr<void> OnExit(pNull, boost::bind(&std::list<A>::pop_front, pList));              // variant 2
      
BFE>      rA.f();
BFE>


я бы использовал swap (или std::move)
{
    A a;
    swap(a, pList->front());
    // или
    // auto a = std::move(pList->front());

    pList->pop_front();

    a.f();
}
In Zen We Trust
Re[3]: do on exit
От: Erop Россия  
Дата: 29.03.13 04:58
Оценка:
Здравствуйте, B0FEE664, Вы писали:

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


Да хоть бы и в рамках старого.
Зачем-то в одном месте собраны и RAII и обработчик прерывания, и всё это ещё в цикл зачем-то засунуто...

Никак нельзя как-то концептуально проще быть?
Попробуй объяснить, что конкретно тебе надо-то?

Пройтись по списку, и выкинуть из него элементы, на которых падает какой-то метод?
Вызвать у всех элементов списка метод, даже если какой-то элемент кинет исключение?
Что-то ещё?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: do on exit
От: Кодт Россия  
Дата: 29.03.13 07:12
Оценка: +3
Здравствуйте, B0FEE664, Вы писали:

BFE>Макросы не предлагать.


BFE>Что лучше variant 1 или 2?

Оба хуже

BFE>И вообще, что бы вы сказали увидев это в проекте?

"Я вам в отцы гожусь", сказал бы настоящий петербуржец.

Проще надо быть, и люди потянутся.
Логика работы ведь какая:
— дёрнуть f() у объекта, находящегося в голове списка
— диагностировать исключение
— удалить объект из головы

Если объекту неважно, лежит он в списке на момент вызова, — то сперва извлечь, потом дёрнуть.
Если важно, то так прямо и написать
while(!theList.empty())
{
  A& obj = theList.front();
  try { obj.f(); }
  catch(std::exception const& e) { report_error(e); }
  catch(...) { assertion_fault("неизвестное исключение! мы все умрём!"); throw; } // нет смысла дальше молотить наш цикл
  theList.pop_front(); // если исключение вылетит отсюда (?!), то тоже нет смысла дальше молотить цикл
}

Безо всяких scope guard-ов.
Перекуём баги на фичи!
Re[4]: do on exit
От: B0FEE664  
Дата: 29.03.13 11:00
Оценка: :))) :))) :)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

BFE>>Неужели в boost нет ничего более подходящего?

EP>Boost.ScopeExit

Нет, макросы мне не нужны.
И каждый день — без права на ошибку...
Re[5]: do on exit
От: Evgeny.Panasyuk Россия  
Дата: 29.03.13 15:01
Оценка: +3
Здравствуйте, B0FEE664, Вы писали:

BFE>>>Неужели в boost нет ничего более подходящего?

EP>>Boost.ScopeExit
BFE>Нет, макросы мне не нужны.

Неужели если бы выбор стоял между тем что было в первом сообщении, и BOOST_SCOPE_EXIT, ты бы выбрал boost::shared_ptr, в котором лишние атомарные инструкции, лишний type erasure и менее читабельный код?
Re[6]: do on exit
От: B0FEE664  
Дата: 29.03.13 16:27
Оценка: :)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

BFE>>>>Неужели в boost нет ничего более подходящего?

EP>>>Boost.ScopeExit
BFE>>Нет, макросы мне не нужны.

EP>Неужели если бы выбор стоял между тем что было в первом сообщении, и BOOST_SCOPE_EXIT, ты бы выбрал boost::shared_ptr, в котором лишние атомарные инструкции, лишний type erasure и менее читабельный код?

Вы ещё про заказ памяти посредством new внутри shared_count забыли

А как вы думаете, зачем я написал первую строчку в первом сообщении?
К счастью, выбор так не стоит, а если бы и стоял, то — да, предпочитаю стандартную практику без макросов см. документацию.


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

EP>>Неужели если бы выбор стоял между тем что было в первом сообщении, и BOOST_SCOPE_EXIT, ты бы выбрал boost::shared_ptr, в котором лишние атомарные инструкции, лишний type erasure и менее читабельный код?

BFE>Вы ещё про заказ памяти посредством new внутри shared_count забыли

new и так уже нужен при type erasure.

BFE>А как вы думаете, зачем я написал первую строчку в первом сообщении?


Сообщение с вопросом про boost, я прочитал намного позже первого, поэтому был не в контексте.

BFE>PS: Но кончилось всё как обычно: написал ещё один класс который только и делает, что pop_front в деструкторе вызывает.


Это кстати намного лучше shared_ptr, а при вероятности реиспользования (если получится дать хорошее имя) даже лучше чем scope exit.
Re[8]: do on exit
От: B0FEE664  
Дата: 29.03.13 17:16
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>>>Неужели если бы выбор стоял между тем что было в первом сообщении, и BOOST_SCOPE_EXIT, ты бы выбрал boost::shared_ptr, в котором лишние атомарные инструкции, лишний type erasure и менее читабельный код?

BFE>>Вы ещё про заказ памяти посредством new внутри shared_count забыли
EP>new и так уже нужен при type erasure.
type erasure можно и на ссылках смастерить. Впрочем зачем type erasure у shared_ptr мне не понятно.

BFE>>PS: Но кончилось всё как обычно: написал ещё один класс который только и делает, что pop_front в деструкторе вызывает.

EP>Это кстати намного лучше shared_ptr, а при вероятности реиспользования (если получится дать хорошее имя) даже лучше чем scope exit.
Как показывает практика, вероятность реиспользования таких классов стремится к нулю.
И каждый день — без права на ошибку...
Re[9]: do on exit
От: Evgeny.Panasyuk Россия  
Дата: 29.03.13 19:21
Оценка:
Здравствуйте, B0FEE664, Вы писали:

EP>>>>Неужели если бы выбор стоял между тем что было в первом сообщении, и BOOST_SCOPE_EXIT, ты бы выбрал boost::shared_ptr, в котором лишние атомарные инструкции, лишний type erasure и менее читабельный код?

BFE>>>Вы ещё про заказ памяти посредством new внутри shared_count забыли
EP>>new и так уже нужен при type erasure.
BFE>type erasure можно и на ссылках смастерить. Впрочем зачем type erasure у shared_ptr мне не понятно.

Ну а как без type erasure сохранить произвольный deleter, не меняя тип shared_ptr<void>?
boost::shared_ptr<void> OnExit(pNull, boost::bind(&std::list<A>::pop_front, pList));

Допустим в качестве deleter'а будет функтор у которого sizeof=1024.
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <ostream>

using namespace std;

struct Deleter
{
    char stuff[1024];
    void operator()(void*){}
};

int main()
{
    boost::shared_ptr<void> p(0,Deleter());
    cout << "sizeof(p)=" << sizeof(p) << endl;
    cout << "sizeof(Deleter)=" << sizeof(Deleter) << endl;
}

stdout:
sizeof(p)=16
sizeof(Deleter)=1024


BFE>Как показывает практика, вероятность реиспользования таких классов стремится к нулю.


Да, согласен.
Re[7]: do on exit
От: Erop Россия  
Дата: 29.03.13 19:33
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>PS: Но кончилось всё как обычно: написал ещё один класс который только и делает, что pop_front в деструкторе вызывает.


А зачем?
Можешь понятно пояснить, что тебе надо-то было?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: do on exit
От: B0FEE664  
Дата: 02.04.13 09:18
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

BFE>>type erasure можно и на ссылках смастерить. Впрочем зачем type erasure у shared_ptr мне не понятно.

EP>Ну а как без type erasure сохранить произвольный deleter, не меняя тип shared_ptr<void>?

Не подумал
И каждый день — без права на ошибку...
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
Re[8]: do on exit
От: BulatZiganshin  
Дата: 20.03.15 10:47
Оценка:
Здравствуйте, nen777w, Вы писали:

N>"Страх рождает гнев, гнев рождает ненависть."(С) не помню кто


дюна. кстати в звёздных войнах очень похожее
Люди, я люблю вас! Будьте бдительны!!!
Re[11]: do on exit
От: B0FEE664  
Дата: 23.03.15 12:58
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

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

EP>Там будет одно перемещение.
точно. С перемещением параметров, что указаны в квадратных скобках.

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


EP>Думаю одно перемещение не настолько страшно, тем более после инлайнинга оно скорей всего испарится.

Не уверен про инлайнинг, но, пожалуй, соглашусь.

EP>Да и теряется возможно обернуть всё это в удобный макрос:



EP>Это был такой тонкий намёк на то что на дворе уже C++14

Да ладно! Я только сегодня понял, что оператор --> можно переопределить:
struct Aux2
{
    const Aux2& operator--(int) const
    {
        return *this;
    }

    template<typename F>
    Guard<typename std::decay<F>::type> operator>(F &&f) const
    {
        return { std::forward<F>(f) };
    }
};

const Aux2 make_at_scope_exit{};


И вместо неясной мультипликации получаем интересный и понятный синтаксис:
        const auto&& guard = make_at_scope_exit7-->[&] { std::cout << "x=" << x << ": guard\n"; };
И каждый день — без права на ошибку...
Re[12]: do on exit
От: Evgeny.Panasyuk Россия  
Дата: 23.03.15 13:12
Оценка:
Здравствуйте, B0FEE664, Вы писали:

EP>>Да и теряется возможно обернуть всё это в удобный макрос:

BFE>

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

EP>>Это был такой тонкий намёк на то что на дворе уже C++14

BFE>Да ладно! Я только сегодня понял, что оператор --> можно переопределить:

Подобным образом можно ещё и именованные операторы
Автор: Evgeny.Panasyuk
Дата: 24.01.14
вводить:
auto fibs = fix(cons(0) * cons(1) * (zipWith(sum) <ap> tail));
auto x = fibs <at> 101;


BFE>И вместо неясной мультипликации получаем интересный и понятный синтаксис:


Подразумевалось что мультипликация будет спрятана в макросе
Re[13]: do on exit
От: B0FEE664  
Дата: 23.03.15 13:45
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>>>Да и теряется возможно обернуть всё это в удобный макрос:

BFE>>
EP>Это же действительно удобно. Не понимаю зачем отказываться от макросов там где они реально упрощают код.
Макросы не упрощают код, они всего лишь прячут его.

EP>Подобным образом можно ещё и именованные операторы
Автор: Evgeny.Panasyuk
Дата: 24.01.14
вводить:

Не, это не то...
А вот оператор "Goes to" реально круто выглядит!
x = b------>asdf;

Не, ну реально круто! Вот, например, как задачка на собеседование. Может ли такой код быть валидным в C++:

a -------> m_n = 0;

Не многие поймут. Мало, кто сможет реализовать... (Да, да. "минусов" нечётное число!)

BFE>>И вместо неясной мультипликации получаем интересный и понятный синтаксис:

EP>Подразумевалось что мультипликация будет спрятана в макросе

А зачем тогда переменная aux? Прятали бы тогда прямо функцию.
И каждый день — без права на ошибку...
Re[14]: do on exit
От: Evgeny.Panasyuk Россия  
Дата: 23.03.15 14:06
Оценка:
Здравствуйте, B0FEE664, Вы писали:

EP>>>>Да и теряется возможно обернуть всё это в удобный макрос:

BFE>>>
EP>>Это же действительно удобно. Не понимаю зачем отказываться от макросов там где они реально упрощают код.
BFE>Макросы не упрощают код, они всего лишь прячут его.

Функции тоже прячут код, тем самым упрощая его, так же как и макросы.

BFE>Не, ну реально круто! Вот, например, как задачка на собеседование.


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

BFE>Может ли такой код быть валидным в C++:

BFE>

BFE> a -------> m_n = 0;

BFE>Не многие поймут. Мало, кто сможет реализовать... (Да, да. "минусов" нечётное число!)

Раз нечётное, то перегрузка -- и -> ?

BFE>>>И вместо неясной мультипликации получаем интересный и понятный синтаксис:

EP>>Подразумевалось что мультипликация будет спрятана в макросе
BFE>А зачем тогда переменная aux? Прятали бы тогда прямо функцию.

Для того что бы был красивый синтаксис:
scope_exit
{
    // ...
};

С функцией вместо }; было бы });, что совсем не по фен-шую.
Re[15]: do on exit
От: B0FEE664  
Дата: 23.03.15 14:30
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

BFE>>Макросы не упрощают код, они всего лишь прячут его.

EP>Функции тоже прячут код, тем самым упрощая его, так же как и макросы.
Функции код не прячут, они его группируют. Разница в способе взаимодействия с окружающим кодом и в количестве кода.

EP>Раз нечётное, то перегрузка -- и -> ?

да.

EP>С функцией вместо }; было бы });, что совсем не по фен-шую.

Понял.
Но всё равно, если речь о макросах, то о фен-шуе говорить не приходится. Как только понадобится сделать dismiss у guard'а или, например, параметры передать в тело лямбды, то начнутся эзотерические изыскания в дебрях макроса...
И каждый день — без права на ошибку...
Re[16]: do on exit
От: Evgeny.Panasyuk Россия  
Дата: 23.03.15 14:48
Оценка: 12 (1)
Здравствуйте, B0FEE664, Вы писали:

BFE>>>Макросы не упрощают код, они всего лишь прячут его.

EP>>Функции тоже прячут код, тем самым упрощая его, так же как и макросы.
BFE>Функции код не прячут, они его группируют. Разница в способе взаимодействия с окружающим кодом и в количестве кода.

В случае с scope_exit не вижу проблем, но естественно нужна документация.

EP>>С функцией вместо }; было бы });, что совсем не по фен-шую.

BFE>Понял.
BFE>Но всё равно, если речь о макросах, то о фен-шуе говорить не приходится. Как только понадобится сделать dismiss у guard'а или,

guard с dismiss'ом это уже совсем другая семантика нежели scope_exit.
Кстати, для таких случаев есть scope_failure:
{
    cout << "success case:" << endl;
    scope(exit)
    {
         cout << "exit" << endl;
    };
    scope(success)
    {
        cout << "success" << endl;
    };
    scope(failure)
    {
        cout << "failure" << endl;
    };
}
cout << string(16,'_') << endl;
try
{
    cout << "failure case:" << endl;
    scope(exit)
    {
        cout << "exit" << endl;
    };
    scope(success)
    {
        cout << "success" << endl;
    };
    scope(failure)
    {
        cout << "failure" << endl;
    };
    throw 1;
}
catch(int){}
// OUTPUT:
success case:
success
exit
________________
failure case:
failure
exit

http://ideone.com/EKsBDB
https://github.com/panaseleus/stack_unwinding
http://rsdn.ru/forum/cpp/4908728.1
Автор: Evgeny.Panasyuk
Дата: 27.09.12


BFE>например, параметры передать в тело лямбды, то начнутся эзотерические изыскания в дебрях макроса...


Какие параметры? Имхо, [&] вполне достаточно для scope_exit.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.