Учитывая этот фрагмент кода:
#define STC_ASSERT(X,Msg) \
(!!sizeof(struct{char STC_ASSERT;_Static_assert((X),Msg "");}))
#define A 43
#define B 42
#define C (STC_ASSERT(A-B>=0,"")?(A-B):0)
enum { c = C };
int main()
{
STC_ASSERT(1,""); //can this not generate a warning on gcc?
}
Могу ли я что-нибудь сделать внутри в оболочке STC_ASSERT
_Static_assert
, чтобы строка в main
не генерировала предупреждение -Wunused-value
при компиляции с gcc -Wall -Wextra
?
(_Pragma
с GCC diagnostic push/pop
здесь не работает. Для макроса, такого как #define FOO 42
, включение его в оператор выражения (({ 42; })
) поможет, но это предотвратит использование макроса в контекстах, где требуется целочисленное постоянное выражение (например, определение enum
))
Clang не генерирует предупреждение (если кто-то может быть вдохновлен этим и поможет OP с GCC). Предложение @Barmar не вызывает предупреждения в GCC.
@Barmar Я в этом не сомневаюсь. По этой причине в вопросе написано «внутри оболочки STC_ASSERT _Static_assert». Я в основном отказался от -Wunused-result с clang после того, как столкнулся с этим bugs.llvm.org/show_bug.cgi?id=39367. Если я не могу заставить этот пример работать с gcc, то я откажусь и от него и с gcc. Мне нравится предупреждение, но за пределами функций изл. помеченный атрибутом warn_unused_result, похоже, отсутствует четкое представление о том, где он должен быть сгенерирован, как его можно вызвать (например, для макросов, основанных на выражениях) и как его можно подавить (например, здесь)).
извините, но побочный вопрос. Вы используете !!sizeof(struct{char STC_ASSERT;...})
в своем STC_ASSERT
, чтобы получить результат 0 или 1 из вашей функции утверждения? Других причин найти не могу.
gcc 8.2 сообщает мне, что -Wunused-value
не -Wunused-result
@Afshin Идея состоит в том, чтобы превратить _Static_assert
в выражение, чтобы его можно было использовать, как в C
(тем самым тесно связав статическое утверждение с определением макроса), сохраняя при этом C
целочисленным константным выражением (чтобы его можно было использовать, например, для определите константу перечислителя c
).
Не могли бы вы определить два макроса: один предназначен для использования в качестве выражения, а другой - в качестве утверждения?
@KamilCuk Спасибо, что заметили. Он должен был сказать -Wunused-value (теперь это так).
примечание: вы можете сократить этот макрос с помощью безымянного битового поля. sizeof(struct { int :1; _Static_assert((X), Msg "" ); })
. Также BUILD_BUG_ON_ZERO
выдает это предупреждение. В любом случае, я бы пошел с двумя макросами - поэтому в ядре есть BUILD_BUG_ON
с ((void)sizeof(...))
и BUILD_BUG_ON_ZERO
, который выражен в выражении.
Но я до сих пор не понимаю, зачем вам нужно превращать _Static_assert
в выражение. Потому что, если произойдет утверждение, код не будет компилироваться (статическое утверждение), а в противном случае у вас всегда будет 1 как C
. Так что я до сих пор не могу понять необходимость преобразования _Static_assert
в выражение. или я упускаю что-то очевидное.
@KamilCuk Спасибо! Мне нравится безымянная идея битового поля.
@Afshin Речь идет о тесной связи статического утверждения с определением макроса значения (макрос C
в приведенном выше коде), который, возможно, оценивается как целочисленное постоянное выражение. Я делаю это в основном потому, что if хорошо вписывается в мою структуру обработки ошибок, которая чем-то напоминает исключения C++ + RAII. В свете этого вы можете думать о макросе C как о { if (A<B) compile_time_throw; else return A-B; }
.
Ага, понял. Большое спасибо за информацию.
Я не думаю, что это можно сделать в самом макросе, так как некоторые вызывающие абоненты используют результат. Может быть, вы сможете записать
(void)STC_ASSERT(1, "");
вmain()
.