Подтвердить что ты не робот

Утверждение С++: приоритет выражения в макроре assert

В С++:

  assert(  std::is_same<int , int>::value  ); // does not compile

  assert( (std::is_same<int , int>::value) ); // compiles

Может кто-нибудь объяснить, почему?

4b9b3361

Ответ 1

Запятая рассматривается как разделитель аргументов для макроса, но скобки в вашем втором случае защищают аргументы. Мы можем это увидеть, перейдя в проект стандартного раздела С++ 16.3 Замена макроса, в котором говорится (внимание мое):

Последовательность токенов предварительной обработки, ограниченных внешними совпадающие круглые скобки образуют список аргументов для функции макро. Отдельные аргументы в списке разделяются запятой токены предварительной обработки, , но токеты предварительной обработки запятой между совпадением Внутренние круглые скобки не разделяют аргументы. Если есть последовательности токены предварительной обработки в списке аргументов, которые в противном случае действуют как предпроцессорные директивы 154, поведение undefined

Мы видим, что макроразложение происходит до семантического анализа, перейдя в раздел 2.2 Фазы перевода и увидим, что фаза 4 включает в себя:

Выполняются предпроцессорные директивы, расширяются макро-вызовы, и [...] Все директивы предварительной обработки затем удаляются.

и фаза 7 включает в себя:

[...] Каждый токен предварительной обработки преобразуется в токен. (2.7). в результате токены синтаксически и семантически анализируются и переведено как единица перевода [...]

В качестве побочного примечания мы видим, что Boost включает специальный макрос для решения этой ситуации: BOOST_PP_COMMA:

Макрос BOOST_PP_COMMA расширяется до запятой.

и говорит:

Препроцессор интерпретирует запятые как разделители аргументов в макросочетаниях. Из-за этого запятые требуют специальной обработки.

и пример:

BOOST_PP_IF(1, BOOST_PP_COMMA, BOOST_PP_EMPTY)() // expands to ,

Ответ 2

assert - макрос препроцессора. Макросы препроцессора тупые; они не понимают шаблонов. Препроцессор видит 10 токенов в круглых скобках:

assert( std :: is_same < int , int > :: value );

Он разбивается на запятую. Он не знает, что это неправильное место для разделения, потому что он не понимает, что std::is_same<int и int>::value являются недопустимыми выражениями С++.

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