С++ void cast и операторская запятая в #define

Я нашел это при чтении некоторого исходного кода.

 #define MACRO(x)  if((void) 0, (x)); else some_func();

Я не совсем понимаю причины, стоящие за этой запятой оператора и литой пустоты. Вероятно, это связано с макрозащитой, я знаю, что (void)0 иногда используется для защиты каскадирования else в макросах, например, в if(...) then foo(); else (void)0.

Любые идеи о том, почему существует служебная запятая?

edit: Я начинаю думать, что это имеет какое-то отношение к owl (0,0).

Ответы

Ответ 1

Я бы предположил, что трюк используется для предотвращения объявления пользователем переменных в состоянии if. Как вы, наверное, знаете, в С++ это законно сделать это

if (int i = some_func()) {
   // you can use `i` here
}
else  {
   // and you can use `i` here
}

Использование оператора запятой в этом определении предотвратит использование макросов, например

MACRO(int i = some_func());

и заставить пользователя использовать только выражения в качестве аргумента.

Ответ 2

Преобразование void определенно предотвратит вызов перегруженного operator ,, так как вы не можете перегрузить параметр void. Это гарантирует, что (void)0, не имеет эффекта.

Зачем нужен оператор запятой? Хороший вопрос. Я действительно не знаю.

Ответ 3

Это немного похоже на то, что кто-то, возможно, начал с некоторого кода, который включал assert, предварительно обработал его и превратил результат в макрос. Когда NDEBUG определяется, assert должен превратиться в почти ничего - но, синтаксически, все равно должен быть произведен некоторый код-заменитель. Например, вы можете использовать его в такой ситуации, как:

assert(x), *x = 1;

Когда вы компилируете это с помощью NDEBUG, он все равно должен компилироваться, но assert не должен ничего делать. Чтобы поддержать это, assert обычно определяется примерно так:

#undef assert
#ifdef NDEBUG
#define assert(x) ((void)0)
#else
#define assert(x) ((!!x) || __failassert(x, __FILE__, __LINE__))
#endif 

Итак, если кто-то начал с кода, как описано выше, а затем посмотрел на предварительно обработанную версию (с определением NDEBUG), они увидели бы что-то вроде:

((void *)0), *x = 1;

... и если они не очень хорошо понимают код, они могут подумать, что ((void)0) действительно что-то означал/что-то сделал.