Я пытаюсь создать простой макрос утверждения, который возвращает логическое значение, но продолжает получать функцию void.
#define FALSE 0
#define TRUE !FALSE
#define CASSERT(predicate) \
({ \
if ((predicate)) \
{ \
(TRUE); \
}else\
{ \
__debugbreak(); \
(FALSE); \
}})
Я хочу использовать это вот так
if (!CASSERT(X==Y)){}
это ошибка, которую я получаю
error: void value not ignored as it ought to be
error: could not convert '<statement>' from 'void' to 'bool'
Я попробовал несколько вариантов этого кода, и ни один из них не работает! вывод CASSERT — это пустая функция!
В новом коде использования используйте stdbool.h вместо доморощенных логических значений. Есть ли причина, по которой вам нужны !TRUE и !!FALSE? Рассмотрите возможность инвертирования значения предиката или замены двух выражений условного оператора.
Если вы пытаетесь использовать выражения операторов GCC (gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html), то ваш синтаксис неверен - переменная с результирующим значением должна быть последней в блоке кода.
@qrdl Да, подтверждаю, в последнем блоке это тоже работает if (!(predicate)) { __debugbreak(); } (predicate); Спасибо
@ ma1169 ma1169 Было бы лучше использовать локальную переменную в выражении оператора, чтобы параметр макроса predicate расширялся только один раз. Например. #define CASSERT(predicate) ({ int result__ = (predicate) ? TRUE : FALSE; if (!result__) { __debugbreak(); } result__; }).





Выполните замену текста самостоятельно.
if (!CASSERT(X==Y)){}
Становится:
if (!{
if ((X==Y)) {
(!0);
}
else {
__debugbreak();
(0);
}}) {}
Это похоже на действительный код C? Это не так, поскольку условный оператор не является выражением, возвращающим логическое значение.
Вы можете использовать условное выражение с оператором запятой для упорядочивания __debugbreak() и FALSE. Что-то вроде:
#define CASSERT(PRED) ((PRED) ? TRUE : (__debugbreak(), FALSE))
Теперь ваш код расширится до:
if (!((X==Y) ? !0 : (__debugbreak(), 1))) {}
Это действительный код C.
Я думаю, что оригинал на самом деле расширяется до if (!({if ((X==Y)){{!0;}else {__debugbreak();0;}})), в котором используется расширение GCC «выражение оператора» ({ … }), где последний оператор в блоке может возвращать значение. Проблема в том, что выражение оператора исходного кода не содержит последнего оператора, возвращающего значение.
Вместо
{ if (predicate) ... else ...}, может быть,(predicate) ? ... : ...?