Здравствуйте, B0FEE664, Вы писали:
BFE>Что лучше variant 1 или 2? BFE>И вообще, что бы вы сказали увидев это в проекте?
Зачем так сложно-то?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Caracrist, Вы писали:
C>если у тебя pop_front упадёт, то catch тебе скорее всего уже не поможет, C>а, иначе, зачем все эти сложности?
Это пример. В реальном коде всё много сложнее. Меня, собственно, интересует не то, как цикл изменить, а то , что вместо этой слишком сложной конструкции подставить:
Здравствуйте, B0FEE664, Вы писали:
BFE>А как надо? (В рамках старого стандарта).
Да хоть бы и в рамках старого.
Зачем-то в одном месте собраны и RAII и обработчик прерывания, и всё это ещё в цикл зачем-то засунуто...
Никак нельзя как-то концептуально проще быть?
Попробуй объяснить, что конкретно тебе надо-то?
Пройтись по списку, и выкинуть из него элементы, на которых падает какой-то метод?
Вызвать у всех элементов списка метод, даже если какой-то элемент кинет исключение?
Что-то ещё?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, 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(); // если исключение вылетит отсюда (?!), то тоже нет смысла дальше молотить цикл
}
Здравствуйте, B0FEE664, Вы писали:
BFE>>>Неужели в boost нет ничего более подходящего? EP>>Boost.ScopeExit BFE>Нет, макросы мне не нужны.
Неужели если бы выбор стоял между тем что было в первом сообщении, и BOOST_SCOPE_EXIT, ты бы выбрал boost::shared_ptr, в котором лишние атомарные инструкции, лишний type erasure и менее читабельный код?
Здравствуйте, Evgeny.Panasyuk, Вы писали:
BFE>>>>Неужели в boost нет ничего более подходящего? EP>>>Boost.ScopeExit BFE>>Нет, макросы мне не нужны.
EP>Неужели если бы выбор стоял между тем что было в первом сообщении, и BOOST_SCOPE_EXIT, ты бы выбрал boost::shared_ptr, в котором лишние атомарные инструкции, лишний type erasure и менее читабельный код?
Вы ещё про заказ памяти посредством new внутри shared_count забыли
А как вы думаете, зачем я написал первую строчку в первом сообщении?
К счастью, выбор так не стоит, а если бы и стоял, то — да, предпочитаю стандартную практику без макросов см. документацию.
PS: Но кончилось всё как обычно: написал ещё один класс который только и делает, что pop_front в деструкторе вызывает.
Здравствуйте, 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.
Здравствуйте, 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.
Как показывает практика, вероятность реиспользования таких классов стремится к нулю.
Здравствуйте, 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>?
Здравствуйте, B0FEE664, Вы писали:
BFE>PS: Но кончилось всё как обычно: написал ещё один класс который только и делает, что pop_front в деструкторе вызывает.
А зачем?
Можешь понятно пояснить, что тебе надо-то было?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Evgeny.Panasyuk, Вы писали:
BFE>>type erasure можно и на ссылках смастерить. Впрочем зачем type erasure у shared_ptr мне не понятно. EP>Ну а как без type erasure сохранить произвольный deleter, не меняя тип shared_ptr<void>?
Здравствуйте, nen777w, Вы писали:
N>Я поражаюсь С++ — офигенный язык, с такими классными возможностями, тут каждый найдёт себе что хочет. N>Одни например goto боятся другие макросов...
Здравствуйте, B0FEE664, Вы писали:
A>>я бы сказал что С++11 больше двух лет, а вы какой-то фигней занимаетесь.
BFE>Ну вот. Мы перешли на новый стандарт.
Здравствуйте, 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
Ну я вот подумал и вижу два варианта, но в коде не уверен, так как не писал ещё такого:
N>>Я поражаюсь С++ — офигенный язык, с такими классными возможностями, тут каждый найдёт себе что хочет. N>>Одни например goto боятся другие макросов...
BFE>Я их не боюсь. Я их ненавижу.
"Страх рождает гнев, гнев рождает ненависть."(С) не помню кто
Здравствуйте, nen777w, Вы писали:
N>>>Я поражаюсь С++ — офигенный язык, с такими классными возможностями, тут каждый найдёт себе что хочет. N>>>Одни например goto боятся другие макросов... BFE>>Я их не боюсь. Я их ненавижу. N>"Страх рождает гнев, гнев рождает ненависть."(С) не помню кто
Здравствуйте, B0FEE664, Вы писали:
N>>>>Я поражаюсь С++ — офигенный язык, с такими классными возможностями, тут каждый найдёт себе что хочет. N>>>>Одни например goto боятся другие макросов... BFE>>>Я их не боюсь. Я их ненавижу. N>>"Страх рождает гнев, гнев рождает ненависть."(С) не помню кто BFE>Зачем макросы если вот здесь
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, Abyx, Вы писали:
A>>можно же просто хранить ссылку, а она продлит время жизни лямбды A>>http://coliru.stacked-crooked.com/a/cf93a63c93859758 BFE>ой ли? BFE>Почему вывод не 42, а непонятное 1?
BFE>
Не, продлевается только время жизни результата выражения — http://coliru.stacked-crooked.com/a/1f4d6e661b5b1eab
В этом кстати засада с expression templates, то есть биндить их к auto&& нужно с осторожностью, а то данные на которые они ссылаются могут разрушиться к моменту вычисления.
Здравствуйте, 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).
Здравствуйте, 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.
Здравствуйте, 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
Здравствуйте, Evgeny.Panasyuk, Вы писали:
BFE>>С Guard более-менее понятно, а вот одно копирование лямбды будет так или иначе(в момент создания Guard). EP>Там будет одно перемещение.
точно. С перемещением параметров, что указаны в квадратных скобках.
BFE>>Видимо надо завести ещё один Guard для указателя на функтор...
EP>Думаю одно перемещение не настолько страшно, тем более после инлайнинга оно скорей всего испарится.
Не уверен про инлайнинг, но, пожалуй, соглашусь.
EP>Да и теряется возможно обернуть всё это в удобный макрос:
EP>Это был такой тонкий намёк на то что на дворе уже C++14
Да ладно! Я только сегодня понял, что оператор --> можно переопределить:
Здравствуйте, B0FEE664, Вы писали:
EP>>Да и теряется возможно обернуть всё это в удобный макрос: BFE>
Это же действительно удобно. Не понимаю зачем отказываться от макросов там где они реально упрощают код.
EP>>Это был такой тонкий намёк на то что на дворе уже C++14 BFE>Да ладно! Я только сегодня понял, что оператор --> можно переопределить:
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>>>Да и теряется возможно обернуть всё это в удобный макрос: BFE>> EP>Это же действительно удобно. Не понимаю зачем отказываться от макросов там где они реально упрощают код.
Макросы не упрощают код, они всего лишь прячут его.
EP>Подобным образом можно ещё и именованные операторы
вводить:
Не, это не то...
А вот оператор "Goes to" реально круто выглядит!
x = b------>asdf;
Не, ну реально круто! Вот, например, как задачка на собеседование. Может ли такой код быть валидным в C++:
a -------> m_n = 0;
Не многие поймут. Мало, кто сможет реализовать... (Да, да. "минусов" нечётное число!)
BFE>>И вместо неясной мультипликации получаем интересный и понятный синтаксис: EP>Подразумевалось что мультипликация будет спрятана в макросе
А зачем тогда переменная aux? Прятали бы тогда прямо функцию.
Здравствуйте, B0FEE664, Вы писали:
EP>>>>Да и теряется возможно обернуть всё это в удобный макрос: BFE>>> EP>>Это же действительно удобно. Не понимаю зачем отказываться от макросов там где они реально упрощают код. BFE>Макросы не упрощают код, они всего лишь прячут его.
Функции тоже прячут код, тем самым упрощая его, так же как и макросы.
BFE>Не, ну реально круто! Вот, например, как задачка на собеседование.
Конечно смотря на какую позицию, но в целом я бы не стал спрашивать ничего подобного.
BFE>Может ли такой код быть валидным в C++: BFE>
BFE> a -------> m_n = 0;
BFE>Не многие поймут. Мало, кто сможет реализовать... (Да, да. "минусов" нечётное число!)
Раз нечётное, то перегрузка -- и -> ?
BFE>>>И вместо неясной мультипликации получаем интересный и понятный синтаксис: EP>>Подразумевалось что мультипликация будет спрятана в макросе BFE>А зачем тогда переменная aux? Прятали бы тогда прямо функцию.
Для того что бы был красивый синтаксис:
scope_exit
{
// ...};
С функцией вместо }; было бы });, что совсем не по фен-шую.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
BFE>>Макросы не упрощают код, они всего лишь прячут его. EP>Функции тоже прячут код, тем самым упрощая его, так же как и макросы.
Функции код не прячут, они его группируют. Разница в способе взаимодействия с окружающим кодом и в количестве кода.
EP>Раз нечётное, то перегрузка -- и -> ?
да.
EP>С функцией вместо }; было бы });, что совсем не по фен-шую.
Понял.
Но всё равно, если речь о макросах, то о фен-шуе говорить не приходится. Как только понадобится сделать dismiss у guard'а или, например, параметры передать в тело лямбды, то начнутся эзотерические изыскания в дебрях макроса...
Здравствуйте, B0FEE664, Вы писали:
BFE>>>Макросы не упрощают код, они всего лишь прячут его. EP>>Функции тоже прячут код, тем самым упрощая его, так же как и макросы. BFE>Функции код не прячут, они его группируют. Разница в способе взаимодействия с окружающим кодом и в количестве кода.
В случае с scope_exit не вижу проблем, но естественно нужна документация.
EP>>С функцией вместо }; было бы });, что совсем не по фен-шую. BFE>Понял. BFE>Но всё равно, если речь о макросах, то о фен-шуе говорить не приходится. Как только понадобится сделать dismiss у guard'а или,
guard с dismiss'ом это уже совсем другая семантика нежели scope_exit.
Кстати, для таких случаев есть scope_failure: