У меня есть макрос, используемый во всем моем коде, который в режиме отладки:
#define contract(condition) \
if (!(condition)) \
throw exception("a contract has been violated");
... но в режиме деблокирования:
#define contract(condition) \
if (!(condition)) \
__builtin_unreachable();
Что это делает над assert()
, так это то, что в сборках релизов компилятор может сильно оптимизировать код благодаря распространению UB.
Например, тестирование с помощью следующего кода:
int foo(int i) {
contract(i == 1);
return i;
}
// ...
foo(0);
... генерирует исключение в режиме отладки, но производит сборку для безусловного return 1;
в режиме выпуска:
foo(int):
mov eax, 1
ret
Условие и все, что от него зависело, были оптимизированы.
Моя проблема возникает с более сложными условиями. Когда компилятор не может доказать, что условие не имеет побочного эффекта, оно не оптимизирует его, что является штрафом за рутину по сравнению с использованием контракта.
Есть ли способ выразить, что условие в контракте не имеет побочного эффекта, так что оно всегда оптимизировано?