Обходной путь для предупреждения «точка с запятой в глобальной области видимости» для макроса no-op C - PullRequest
0 голосов
/ 25 декабря 2018

В кодовой базе, которая может быть построена как C или C ++, я подумал, что сделаю макрос, использующий преимущества static_assert в случае, если он построен как C ++ 11 или выше.

(Примечание: я знаю, есть способы сделать это до C11 C , по крайней мере, если вы хотите принять параметр сообщения - хотя он не будет работать везде.в качестве аргумента, скажем, у меня есть законная необходимость сделать так, чтобы оно не принимало сообщений и не использовалось, по крайней мере, в некоторых сборках C.)

Итак, вот простое определение, которое я попробовал:

#if defined(__cplusplus) && __cplusplus >= 201103L
    #define STATIC_ASSERT(cond) \
        static_assert((cond), #cond)
#else
    #define STATIC_ASSERT(cond)
#endif

В макросе нет точки с запятой с намерением добавить его на месте вызова.Но в педантичных настройках предупреждений C этот макрос, появляющийся в глобальной области видимости, вызывает:

ошибка: ISO C не допускает дополнительного ';'за пределами функции [-Werror = pedantic]

Простое решение, по-видимому, состоит в том, чтобы убрать точку с запятой с сайтов вызовов и поместить ее в сторону макроса на C ++ 11.Но мне интересно: как сделать макрос в режиме без операции в глобальной области видимости, который позволяет использовать точку с запятой на месте вызова (без какого-либо другого предупреждения)?

1 Ответ

0 голосов
/ 25 декабря 2018

Поскольку предварительные объявления структур могут повторяться столько раз, сколько мы хотим, вы можете использовать фиктивное объявление:

#define STATIC_ASSERT(cond) struct GlobalScopeNoopTrick

@ JonathanLeffler говорит, что это должно работать в старых компиляторах, даже до C11 ...но:

"Если у вас есть компилятор C90, он будет возражать, если у вас будет статическое утверждение после оператора в составном операторе . Это не ваша основная задача (этовсегда будет в порядке в области видимости файла, если статическое утверждение также в порядке), но оно не ограничено использованием в области видимости файла. Риск низкий, хотя "

Для связанных ситуаций, которыево время компиляции не может быть полностью no-ops, в C11 появилась возможность повторять typedefs.И, как показано в посте, связанном со статическими утверждениями в C до _Static_assert () , есть способы обойти дублирование typedef для старых C, используя номер строки или другой неоднозначный аргумент:

/* Standard indirection to allow concatenation after expansion */
#define CONCAT(a,b) CONCAT_(a,b)
#define CONCAT_(a,b) a##b

#if defined(__cplusplus) && __cplusplus >= 201103L
    #define STATIC_ASSERT(cond) \
        static_assert((cond), #cond)
#else
    #define STATIC_ASSERT(cond) typedef void CONCAT(dummy_unused_,__LINE__)
#endif

Пока статические утверждения появляются по одному на строку, идентификаторы не будут конфликтовать друг с другом.

...