Ответ 1
Пожалуйста, не делайте этого в проекте, который я управляю. Это неудобное злоупотребление лямбдами, на мой взгляд.
Используйте goto
, где полезен goto
.
Как мы все знаем, это не так просто break
из вложенного цикла из внешнего цикла без:
goto
(Пример кода.)break
ing (Пример кода.)Хотя, вы должны признать, что все это довольно неуклюжие. В частности, версия функции отсутствует из-за недостающего контекста, в котором вызывается цикл, поскольку вам нужно передать все, что вам нужно, в циклы в качестве параметров.
Кроме того, второй становится хуже для каждого вложенного цикла.
Итак, я лично считаю, что версия goto
является самой чистой.
Теперь, думая все С++ 0x и прочее, третий вариант привел меня к этой идее с использованием лямбда-выражений:
#include <iostream>
bool CheckCondition(){
return true;
}
bool CheckOtherCondition(){
return false;
}
int main(){
[&]{while(CheckCondition()){
for(;;){
if(!CheckOtherCondition())
return;
// do stuff...
}
// do stuff...
}}();
std::cout << "yep, broke out of it\n";
}
Это позволяет использовать семантическую красоту простого return
, который предлагает третий вариант, не страдая от проблем контекста и будучи (почти) чистым, как версия goto
. Он также еще короче (характерно), чем любой из вышеперечисленных вариантов.
Теперь я научился сохранять радость после того, как нашел прекрасное (ab) использование языка, потому что почти всегда есть какой-то недостаток. Есть ли что-нибудь на этом? Или есть даже лучший подход к проблеме?
Пожалуйста, не делайте этого в проекте, который я управляю. Это неудобное злоупотребление лямбдами, на мой взгляд.
Используйте goto
, где полезен goto
.
Совершенно верно на мой взгляд. Хотя я предпочитаю назначать мои имена, делая код более самостоятельным документированием, т.е.
int main(){
auto DoThatOneThing = [&]{while(CheckCondition()){
for(;;){
if(!CheckOtherCondition())
return;
// do stuff...
}
// do stuff...
}};
DoThatOneThing();
std::cout << "yep, broke out of it\n";
}
В каком смысле это улучшение над
void frgleTheBrgls()
{
while(CheckCondition()) {
for(;;) {
if(!CheckOtherCondition())
return;
// do stuff...
}
// do stuff...
}
}
int main()
{
frgleTheBrgls();
std::cout << "yep, broke out of it\n";
}
Это хорошо известно (функции, как вы знаете, как в BASIC), яснее (алгоритм получил хорошее имя, объясняющее, что он делает), и делает то же самое, что и ваш.
В частности, версия функции отсутствует из-за недостающего контекста, где вызывается цикл, так как вам нужно передать все, что вам нужно, в циклы в качестве параметров.
Я вижу это как преимущество. Вы точно видите, что нужно для того, чтобы взломать brgls. Объяснение, при программировании, часто является хорошей вещью.
Один из недостатков вашего предложенного синтаксиса: вы не можете иметь более двух вложенных циклов. Синтаксис 'goto' позволяет это:
int main()
{
for (;;)
{
for (;;)
{
for (;;)
{
if (CheckCondition1()) goto BREAK_ON_COND1;
if (CheckCondition2()) goto BREAK_ON_COND2;
if (CheckCondition3()) break;
// Do stuff when all conditions are false
}
// Do stuff when condition 3 becomes true
}
BREAK_ON_COND2:
// Do stuff when condition 2 becomes true
}
BREAK_ON_COND1: // When condition 1 becomes true
std::cout << "yep, broke out of it\n";
}