В Оберон (точнее в один из его диалектов), где, как известно нет исключений и подобных механизмов, предлагается ввести новую синтаксическую конструкцию :
Первый_этап;
IF первый этап удался THEN
Второй_этап
AND второй этап удался THEN
Третий_этап
AND третий этап удался THEN
Завершающие действия
ELSE
Задача не выполнена
END
Соотвественно если нам нужно определить на каком этапе случилась ошибка, то пишется это так:Но это конечно трубует менять язык. Соответственно менять компилятор. Что не здорово, лень и вообще не факт что кто-то будет делать.step := 1; Первый_этап; IF первый этап удался THEN step := 2; Второй этап; AND второй этап удался THEN ... ELSE Log.String("Ошибка на этапе "); Log.Int(step) END
Однако в С++ мы иногда тоже не можем пользоваться исключениями. Ну, например если мы от них намерянно отказались (см. например Google C++ Style). Менять компилятор С++ тоже совсем не интересно, но это и не нужно. Всё вышеперечисленное легко реализуется средствами самого языка, при чем без шаблонов и прочего метапрограммирования.
Нам достаточно того, что в С++ есть оператор запятая (,) и есть ленивые вычисления. Соответственно концепт такой:
Ну и, как обычно, рабочий пример:bool r = ( A1, // первый этап A2, A3, первый_этап_удался ) and ( B1, // второй этап B2, B3, второй_этап_удался ) and ( C1, // третий этап C2, C3, третий_этап_удался ) and ( Z1, // завершаюшие действия Z2, Z3, true ) or ( ERR1, // Задача не выполнена ERR2, ERR3, false);
Соответственно результат запуска такой:#include <iostream> bool zoo(int c) { int z = c; int step = 1; bool r = ( step = 1, z--, std::cout << "step 1: " << z << std::endl, z > 0 ) and ( step = 2, z-- , std::cout << "step 2: " << z << std::endl, z > 0 ) and ( step = 3, z--, std::cout << "step 3: " << z << std::endl, z > 0 ) and ( z = z*z, std::cout << "Ending... " << z << std::endl, true ) or ( std::cout << "Error on step " << step << std::endl, false ); return r; } int main() { zoo(4); zoo(3); zoo(2); zoo(1); zoo(0); }
step 1: 3 step 2: 2 step 3: 1 Ending... 1 step 1: 2 step 2: 1 step 3: 0 Error on step 3 step 1: 1 step 2: 0 Error on step 2 step 1: 0 Error on step 1 step 1: -1 Error on step 1