В С++:
assert( std::is_same<int , int>::value ); // does not compile
assert( (std::is_same<int , int>::value) ); // compiles
Может кто-нибудь объяснить, почему?
В С++:
assert( std::is_same<int , int>::value ); // does not compile
assert( (std::is_same<int , int>::value) ); // compiles
Может кто-нибудь объяснить, почему?
Запятая рассматривается как разделитель аргументов для макроса, но скобки в вашем втором случае защищают аргументы. Мы можем это увидеть, перейдя в проект стандартного раздела С++ 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 ,
assert
- макрос препроцессора. Макросы препроцессора тупые; они не понимают шаблонов. Препроцессор видит 10 токенов в круглых скобках:
assert( std :: is_same < int , int > :: value );
Он разбивается на запятую. Он не знает, что это неправильное место для разделения, потому что он не понимает, что std::is_same<int
и int>::value
являются недопустимыми выражениями С++.
Препроцессор достаточно умен, чтобы не разбить содержимое внутренних пар круглых скобок на несколько аргументов. Поэтому добавление дополнительных круглых скобок устраняет проблему.