В Оберон (точнее в один из его диалектов), где, как известно нет исключений и подобных механизмов, предлагается ввести новую синтаксическую конструкцию :
Первый_этап;
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
2 комментария:
С небольшой переделкой работает и в сях (TinyCC). Но всё же выглядит это страшно...
#include
#define bool int
#define true 1
#define false 0
#define and &&
#define or ||
bool zoo(int c)
{
int z = c;
int step = 1;
bool r = (
step = 1,
z--,
printf("step 1: %d\n", z),
z > 0 ) and (
step = 2,
z-- ,
printf("step 2: %d\n", z),
z > 0 ) and (
step = 3,
z--,
printf("step 3: %d\n", z),
z > 0 ) and (
z = z*z,
printf("Ending... %d\n", z),
true ) or (
printf("Error on step %d\n", step),
false );
return r;
}
int main()
{
zoo(4);
zoo(3);
zoo(2);
zoo(1);
zoo(0);
}
Ну понятно что смотрится не привычно. Также будут скорее всего с шаганием в отладке через gdb (в мелкомягкой студии проблем с этим нет вроде бы). Т.е. gdb скорее всего посчитает вот это вот всё за один шаг. Хотя-я.. Надо попробовать.
Также надо что-то придумать с коментариями к блогспоту, а то это ж не нормально когда в комменты даже код не воткнуть нормально.
Отправить комментарий